﻿#pragma once
//#include "AbstractWrapper.h";
#include <iostream>
#include <string>
#include <cctype>
#include <map>
#include <vector>
#include <ctype.h>
#include <stack>
#include <algorithm>
#include <sstream>
#include "QueryProcessor.h"
#include <set>
using namespace std;
string errors[10];





// Query Preprocessor functions for query parser.
inline string QueryProcessor::trim(string& str)
{
	str.erase(0, str.find_first_not_of(' '));      
	str.erase(str.find_last_not_of(' ')+1);         
	return str;
}

void QueryProcessor::toLowerCase(string &str)
{
	const int length = str.length();
	for(int i=0; i < length; ++i)
	{
		str[i] = std::tolower(str[i]);
	}
}

string QueryProcessor::filterQuote(string dashStr){
	if((dashStr.length()>1)&&(dashStr.substr(0,1)=="\"")){
		dashStr=dashStr.substr(1);
		dashStr=dashStr.substr(0,dashStr.length()-1);
	}
	return dashStr;
}

int QueryProcessor::is_digit (int c)
{
    if (c >= '0' && c <='9')
        return 1;
    else
        return 0;
}

string QueryProcessor::filterDash(string dashStr){
	if((dashStr.length()>1)&&(dashStr.substr(0,1)=="_")){
		dashStr=dashStr.substr(1);
		dashStr=dashStr.substr(0,dashStr.length()-1);
		dashStr=filterQuote(dashStr);
	}
	return dashStr;
}

void QueryProcessor::explode(string str, string separator, vector<string>* results){
    int found;
    found = str.find_first_of(separator);
    while(found != string::npos){
        if(found > 0){
            results->push_back(str.substr(0,found));
        }
        str = str.substr(found+1);
		
        found = str.find_first_of(separator);
    }

    if(str.length()> 0){		
        results->push_back(str);
    }
}

string QueryProcessor::capitalize(string str)
{
	string::iterator it(str.begin());

	if (it != str.end())
		str[0] = toupper((unsigned char)str[0]);

	while(++it != str.end())
	{
		*it = tolower((unsigned char)*it);
	}
	return str;
}

string& QueryProcessor::replace(string& str,const string& old_value,const string& new_value)   
{   
    for(string::size_type pos(0); pos!=string::npos; pos+=new_value.length()){   
        if((pos=str.find(old_value,pos))!=string::npos   )   
            str.replace(pos,old_value.length(),new_value);   
        else break;   
    }   
    return str;   
} 

int QueryProcessor::priority(char a) {
	int temp=0;
	if (a == '^'){
		temp = 1;
	}else if (a == '*' || a == '/'){
		temp = 2;
	}else if (a == '+' || a == '-'){
		temp = 3;
	}else if (a=='('){
		temp=4;
	}
	return temp;
}



size_t QueryProcessor::findOp(string str){
	size_t plus_p=str.find("+");
	size_t minus_p=str.find("-");
	size_t times_p=str.find("*");

	size_t temp=1000;

	if(plus_p>=0&&plus_p<100){
		if(plus_p<temp)
			temp=plus_p;
	}
	if(minus_p>=0&&minus_p<100){
		if(minus_p<temp)
			temp=minus_p;
	}
	if(times_p>=0&&times_p<100){
		if(times_p<temp)
			temp=times_p;
	}

	return temp;
}

string QueryProcessor::convertInt(int number)
{
   stringstream ss;
   ss << number;
   return ss.str();
}

vector<string> splitS(string s, char sep) {
	vector<string> strvec;
	string strtemp;
	string::size_type pos1, pos2;
	pos2 = s.find(sep);
	pos1 = 0;        
	while (string::npos != pos2)
	{
		strvec.push_back(s.substr(pos1, pos2 - pos1));
		pos1 = pos2 + 1;
		pos2 = s.find(sep, pos1);
	}
	strvec.push_back(s.substr(pos1));
	return strvec;
}

string trimL(string aimString) {
	string output;
	int p = aimString.find_first_not_of(" \r\t");
	output = aimString.substr(p);
	return output;
}

string QueryProcessor::convertName(string name, map<string,string> args)
{

	vector<string> temp;
	//toLowerCase(name);
	explode(name, ".", &temp);


	if(temp.size()>1){
		string ck=trim(temp.at(1));
		string nm=trim(temp.at(0));
		toLowerCase(ck);
		
		if(ck=="procname"){
			if(args[nm]=="Call"){
				return "CallProc";
			}else{
				return nm;
			}
		}
			
		if(ck=="varname"||ck=="value"||ck=="stmt#"){
			return nm;
		}

		return name;
	}
   return name;
}

string QueryProcessor::splitString(string input,int pos){
	vector<string> temp;
	explode(input,".",&temp);
	return temp.at(pos);
}



bool QueryProcessor::queryParser(){
	string temp, tempName, tempType, query, body_query, select_query, func_query, pattern_query, paramType;
	size_t p,p1,select_p,function_p=0,pattern_p=0, with_p=0;
	map<string,string> args;
	set<string> sync;
	set<string> stFunc;
	set<string> otFunc;
	set<string> argList;
	QueryProcessor qp;

	query=trim(_query.first);
	//assign variables
	vector<string> defination;
	explode(query, ";", &defination);	

	argList.insert("Assign");
	argList.insert("Statement");
	argList.insert("Assignment");
	argList.insert("Stmt");
	argList.insert("Stmtlst");
	argList.insert("Procedure");
	argList.insert("Plus");
	argList.insert("Minus");
	argList.insert("Times");
	argList.insert("Variable");
	argList.insert("Prog_line");
	argList.insert("While");
	argList.insert("If");
	argList.insert("Call");
	argList.insert("Constant");


	for(size_t i=0;i<defination.size();i++){
		temp=trim(defination[i]);
		//cout<<temp<<endl;
		vector<string> param;
		//explode(temp," ",&param);
		//paramType=trim(param[0]);
		
		p=temp.find_first_of(" ");
		paramType=temp.substr(0,p);
		toLowerCase(paramType);

		if(paramType=="stmt"||paramType=="prog_line"){
			paramType="statement";
		}else if(paramType=="assignment"){
			paramType="assign";
		}

		paramType=capitalize(paramType);
		//v
		if(argList.find(paramType)==argList.end()){
			cout<<paramType+" type not allowed"<<endl;
			return false;
		}
		
		temp=trim(temp.substr(p));

		//p=param[1].find(",");
		p=temp.find(",");

		
		if(p>0&&p<10){
			vector<string> subParam;
			//explode(param[1],",",&subParam);
			explode(temp,",",&subParam);
			for(size_t j=0;j<subParam.size();j++){

				args[trim(subParam[j])]=paramType;
			}
		
		}else{
			args[trim(temp)]=paramType;
		}
	}


	//Select a such that Follows (w, a) pattern a (“x”,_)
	query=trim(_query.second);
	temp=query;
	toLowerCase(temp);

	//check query
	p=temp.find("select");
	if(p>=0&&p<100) select_p=p;
	p=temp.find("such");
	if(p>0&&p<100) function_p=p;
	p=temp.find("pattern");
	if(p>0&&p<100) pattern_p=p;
	p=temp.find("with");
	if(p>0&&p<100) with_p=p;

	if(function_p==0&&pattern_p==0&&with_p==0){
		select_query=query.substr(0);
		body_query="";
	}else{
		vector<int> pos;

		if(function_p>0){
			pos.push_back(function_p);
		}

		if(pattern_p>0){
			pos.push_back(pattern_p);
		}

		if(with_p>0){
			pos.push_back(with_p);
		}
		int min_p=100000;

		for(size_t m=0;m<pos.size();m++){
			if (min_p>pos.at(m)){
				min_p=pos.at(m);
			}
		}


		select_query=query.substr(0,min_p);
		//body_query=temp.substr(min_p);
		body_query=query.substr(min_p);

/*
		if(function_p>0&&pattern_p==0){
			select_query=temp.substr(0,function_p);
			body_query=temp.substr(function_p);
		}else if(function_p==0&&pattern_p>0){
			select_query=temp.substr(0,pattern_p);
			body_query=temp.substr(pattern_p);
		}else if(function_p>0&&pattern_p>0){
			if(function_p<pattern_p){
				select_query=temp.substr(0,function_p);
				body_query=temp.substr(function_p);
			}else{
				select_query=temp.substr(0,pattern_p);
				body_query=temp.substr(pattern_p);
			}
		}
		*/
	}
	
	body_query=replace(body_query,"such that","|");
	body_query=replace(body_query,"with","| with (");
	body_query=replace(body_query,"and","| and");
	body_query=replace(body_query,"pattern","| pattern");

	//cout<<select_query<<endl;

	select_query=trim(select_query);

	if(select_query!=""){
		temp=select_query.substr(0,6);
		toLowerCase(temp);
		if(temp!="select"){
			//cout << "no select" <<endl;
			return false;
		}

		temp=select_query.substr(6);

		//get selected arg
		temp=trim(temp);

		selectQuery_t select;
		string tempCall;

		if(temp=="BOOLEAN"){
			select.SelectType="Boolean";
			selectType=3;
		}else{
			p=temp.find("<");
			if(p>=0&&p<100){
				temp=temp.substr(1);
				temp=temp.substr(0,temp.size()-1);
				vector<string> subTuple;
				explode(temp,",",&subTuple);
				selectType=5;
				string tempS;
				for(size_t j=0;j<subTuple.size();j++){
					tempS=subTuple.at(j);
					tempS=trim(tempS);
					temp=tempS;
					tempS=convertName(tempS,args);

					if(tempS=="CallProc"){
						select.tupleName.push_back(temp);
						select.tupleType.push_back(tempS);
						temp=splitString(temp,0);
						sync.insert(temp);
					}else{
						select.tupleName.push_back(tempS);
						select.tupleType.push_back(args[tempS]);
					}

					if(args[tempS]=="Call"){
						toLowerCase(tempS);
						sync.insert(tempS);
					}
					//cout<<select.tupleType.at(j)+"->"+select.tupleName.at(j)<<endl;
				}
				select.SelectType="tuple";
			}else{
				//for call
				tempCall=temp;
				temp=convertName(temp,args);
				if(temp=="CallProc"){
					select.SelectType="CallProc";
				}else{
					select.SelectType=args[temp];
				}

				if(select.SelectType=="Procedure"||select.SelectType=="CallProc"){
					selectType=4;
				}else if(select.SelectType=="Variable"){
					selectType=2;
				}else if(select.SelectType=="Constant"){
					selectType=6;
				}else{
					selectType=1;
				}
			}
		}

		select.SelectName=temp;
		selectedArgName=temp; 
		if(temp=="CallProc"){
			toLowerCase(tempCall);
			select.SelectName=tempCall;
			selectedArgName=tempCall;
			
			temp=splitString(tempCall,0);
			sync.insert(temp);
		}
		
		
		tempType=args[temp];
		toLowerCase(tempType);

		if(tempType=="call"){
			temp=splitString(tempCall,0);		
			toLowerCase(temp);
			sync.insert(temp);
		}else if(tempType=="stmtlst"){
			select.SelectType="StmtLst";
		}else if(tempType=="plus"){
			select.SelectType="+";
		}else if(tempType=="minus"){
			select.SelectType="-";
		}else if(tempType=="times"){
			select.SelectType="*";
		}


		queries.selectQuery=select;


		//isSelectLineNum=true;
		//if(select.SelectType=="Variable") isSelectLineNum=false;
		//cout<<"select:=============="<<endl;
		//cout<< select.SelectType+","+select.SelectName+",";
		//cout<< <<endl;

		//if(function_p==0&&pattern_p==0) return true;
	}

	//cout<<body_query<<endl;

	vector<string> subQuery;
	explode(body_query, "|", &subQuery);	


	//cout<<queries.size()<<endl;
				stFunc.insert("follows");
			stFunc.insert("follows*");
			stFunc.insert("affects");
			stFunc.insert("affects*");
			stFunc.insert("affectsbip");
			stFunc.insert("affectsbip*");
			stFunc.insert("parent");
			stFunc.insert("parent*");
			stFunc.insert("next");
			stFunc.insert("next*");
			stFunc.insert("nextbip");
			stFunc.insert("nextbip*");

			otFunc.insert("contains");
			otFunc.insert("contains*");
			otFunc.insert("modifies");
			otFunc.insert("uses");
			otFunc.insert("calls");
			otFunc.insert("calls*");
	if(subQuery.size()>0){
		string possibleType;

		for(size_t i=0;i<subQuery.size();i++){
			temp=trim(subQuery[i]);

			if(temp.substr(0,3)=="and"){
				temp=temp.substr(3);
				temp=trim(temp);

				subQuery[i]=temp;

				p=temp.find("(");

				if(p>=0&&p<100){
					tempName=temp.substr(0,p);
					tempName=trim(tempName);
					toLowerCase(tempName);

					if((stFunc.find(tempName)==stFunc.end())||otFunc.find(tempName)==otFunc.end()){
						possibleType="pattern";
					}
				}else{
					possibleType="with";
				}



				if(i>0){
					if(subQuery[i-1].substr(0,4)=="with"&&possibleType=="with"){
						subQuery[i]="with ("+temp;
					}else if(subQuery[i-1].substr(0,7)=="pattern"&&possibleType=="pattern"){
						subQuery[i]="pattern "+temp;
					}
				}
			}



		}



		for(size_t i=0;i<subQuery.size();i++){
			temp=trim(subQuery[i]);
			//cout<<temp<<endl;
			p=temp.find("(");

			if(p>=0&&p<100){
				tempName=temp.substr(0,p);
			}
			tempName=trim(tempName);

			toLowerCase(tempName);



			if((stFunc.find(tempName)!=stFunc.end())||otFunc.find(tempName)!=otFunc.end()){		
				funcQuery_t func;
				func.FunctionType=trim(tempName);

				temp=temp.substr(p+1);
				p1=temp.find(",");
				func.FirstElementName=temp.substr(0,p1);
				func.FirstElementName=trim(func.FirstElementName);

				temp=temp.substr(p1+1);
				
				p1=temp.find(",");
				//v
				if(p1>=0&&p1<100){
					cout<<"Too many Parameter"<<endl;
					return false;
				}

				p1=temp.find(")");
				func.SecondElementName=temp.substr(0,p1);
				func.SecondElementName=trim(func.SecondElementName);

				char *check = (char*)func.FirstElementName.c_str();
				if(!isdigit(check[0])){	

					if(func.FirstElementName=="_"){
						func.FirstElementType="Statement";
					}else if((func.FirstElementName.substr(0,1)=="\"")&&(otFunc.find(tempName)!=otFunc.end())){
						func.FirstElementName=filterQuote(func.FirstElementName);
						func.FirstElementType="String";
					}else{
						func.FirstElementName=convertName(func.FirstElementName,args);
						func.FirstElementType=args[func.FirstElementName];
					}
				}else{
					if(tempName=="contains"||tempName=="contains*"){
						func.FirstElementType="Integer";
					}else{
						func.FirstElementType="Constant";
					}
				}
				tempType=func.FirstElementType;
				toLowerCase(tempType);

				if(tempType=="plus"){
					func.FirstElementType="+";
				}else if(tempType=="times"){
					func.FirstElementType="*";
				}else if(tempType=="minus"){
					func.FirstElementType="-";
				}else if(tempType=="stmtlst"){
					func.FirstElementType="StmtLst";
				}

				check = (char*)func.SecondElementName.c_str();
				if(!isdigit(check[0])){

					if(tempName=="modifies"||tempName=="uses"||tempName=="modifies*"||tempName=="uses*"){
						if(func.SecondElementName!="_"){
							if(func.SecondElementName.substr(0,1)!="\""){
								func.SecondElementType="Variable";
							}else{
								func.SecondElementType="Expression";
								func.SecondElementName=filterQuote(func.SecondElementName);
								func.SecondElementName=filterDash(func.SecondElementName);
							}
						}else{
							func.SecondElementType="Statement";
						}
					}else if(func.SecondElementName=="_"){
						func.SecondElementType="Statement";
					}else if((func.SecondElementName.substr(0,1)=="\"")&&(tempName=="calls"||tempName=="calls*"||tempName=="contains"||tempName=="contains*")){
						func.SecondElementName=filterQuote(func.SecondElementName);
						func.SecondElementType="String";
					}else{
						func.SecondElementName=convertName(func.SecondElementName,args);
						func.SecondElementType=args[func.SecondElementName];
					}
				}else{
					if(tempName=="contains"||tempName=="contains*"){
						func.SecondElementType="Integer";
					}else{
						func.SecondElementType="Constant";
					}
				}


				tempType=func.SecondElementType;
				toLowerCase(tempType);

				if(tempType=="plus"){
					func.SecondElementType="+";
				}else if(tempType=="times"){
					func.SecondElementType="*";
				}else if(tempType=="minus"){
					func.SecondElementType="-";
				}else if(tempType=="stmtlst"){
					func.SecondElementType="StmtLst";
				}
				//v
				if((stFunc.find(func.FirstElementName)!=stFunc.end())||otFunc.find(func.FirstElementName)!=otFunc.end()||stFunc.find(func.SecondElementName)!=stFunc.end()||otFunc.find(func.SecondElementName)!=otFunc.end()){
					cout<<"Nested relationship no allowed"<<endl;
					return false;
				}
				if(func.FirstElementType==""||func.SecondElementType==""){
					cout<<"Variable no declared"<<endl;
					return false;
				}
				//cout<<"functions:============="<<endl;
				//cout<<func.FirstElementType+","+func.FirstElementName+","+func.FunctionType<<endl;
				//cout<<func.SecondElementType+","+func.SecondElementName+","+func.FunctionType<<endl;
				queries.funcQueries.push_back(func);
			}else if(tempName.substr(0,7)=="pattern"){


				
				tempName=tempName.substr(8);
				tempName=trim(tempName);

				patternQuery_t pattern;
				pattern.ElementName=tempName;
				
				pattern.ElementType=args[tempName];

				temp=temp.substr(p+1);
				p1=temp.find(",");
				pattern.VarRef=temp.substr(0,p1);
				pattern.VarRef=trim(pattern.VarRef);

				if(pattern.VarRef.substr(0,1)=="\""||pattern.VarRef=="_"){

					pattern.isVarRefVariable=false;
					pattern.VarRef=trim(filterQuote(pattern.VarRef));
				}else{

					pattern.isVarRefVariable=true;
				}

				/*
				if(pattern.isVarRefVariable==true)
					cout<<"var ref is true"<<endl;

				if(pattern.isVarRefVariable==false)
					cout<<"var ref is false"<<endl;
					*/
				temp=temp.substr(p1+1);

				string tempIf=pattern.ElementType;
				toLowerCase(tempIf);
				if(tempIf=="if"){
					p1=0;
					p1=temp.find(",");

					if(p1<0||p1>100){
						//cout<<"Wrong number of parameter for if function"<<endl;
						throw string("Some Var");
						return false;
					}
				}else{
					p1=temp.rfind(")");
				}
				temp=temp.substr(0,p1);
				temp=trim(temp);
				if(temp.substr(0,1)=="\""||temp.substr(0,1)=="_"){
					if(temp.substr(0,1)=="_"){
						pattern.ExpWithUnderscore=true;
					}else{
						pattern.ExpWithUnderscore=false;
					}
					temp=filterQuote(temp);
					temp=filterDash(temp);
				}
				temp=trim(temp);

				stack<char> op_stack;
				//string infix="1+3*2/4";
				//ststring infix="2*3+1-4
				string input=temp;

				if(input.length()>1){
					string infix="";

					int m=0;
					vector<string> patternVars;
					
					string subString="";
					string ch;

					while(input!=""){
						/*
						p1=findOp(input);
						if(p1>0&&p1<1000){
							patternVars.push_back(trim(input.substr(0,p1)));
							infix+=convertInt(m)+trim(input.substr(p1,1));
							input=input.substr(p1+1);
						}else{
							patternVars.push_back(trim(input));
							input="";
							infix+=conviertInt(m);
						}
						m++;*/
	
						ch=input.substr(0,1);
						if(ch=="+"||ch=="-"||ch=="*"||ch=="/"||ch=="("||ch==")"){
							if(subString!=""){
								patternVars.push_back(trim(subString));
								infix+=convertInt(m);
								subString="";
								m++;
							}
							infix+=trim(ch);
							
						}else{
							subString=subString+ch;
						}
						input=input.substr(1);
						input=trim(input);
					}
					if(subString!=""){
						patternVars.push_back(trim(subString));
						infix+=convertInt(m);
						subString="";
					}					
					//cout<<"-----------------------------i am infix  "+infix<<endl;
					/*
					for(int i=0; i<patternVars.size(); i++){
						cout<<patternVars.at(i)<<endl;
					}

					cout<<"infix:"+infix<<endl;
					*/
					string output;

					for (unsigned i = 0; i < infix.length(); i++) {
						//cout<<i<<endl;
						if (infix[i] == '+' || infix[i] == '-' || infix[i] == '*' || infix[i] == '/') {
							while (!op_stack.empty() && priority(op_stack.top()) <= priority(infix[i])) {
								output.push_back(op_stack.top());
								op_stack.pop();
							}
							op_stack.push(infix[i]);
						} else if (infix[i] == '(') {
							op_stack.push(infix[i]);
						} else if (infix[i] == ')') {
							while (op_stack.top() != '(') {
								output.push_back(op_stack.top());
								op_stack.pop();
							}
							op_stack.pop();
						}else{
							output.push_back(infix[i]);
						}
					}

					while (!op_stack.empty()) {
						output.push_back(op_stack.top());
						op_stack.pop();
					}
			
					//cout<<"i am output +++++++++++  "+output;

					std::reverse(output.begin(), output.end());

					vector<Pattern_node> qs;
					vector<int> os;
					int y=0;

					

					while(output!=""){
						Pattern_node temp;
						temp.setData(output.substr(0,1));
						//temp.data=output.substr(0,1);
						if(os.size()>0){
							int d=os.size();
							while(d>0){
								d=d-1;
								int osIndex=os.at(d);
								if(qs.at(osIndex).getRight()==0){
									qs.at(osIndex).setRight(y);
									break;
								}else if(qs.at(osIndex).getLeft()==0){
									qs.at(osIndex).setLeft(y);
									break;
								}
							}
						}
						//if(temp.getData()=="+"||temp.getData()=="-"||temp.getData()=="/"||temp.getData()=="*"){
						//temp.setRight(0);
						//temp.setLeft(0)
						if(temp.getData()=="+"||temp.getData()=="-"||temp.getData()=="/"||temp.getData()=="*"){
							temp.setRight(0);
							temp.setLeft(0);
							os.push_back(y);
						}else{
							
							int varIndex=atoi(temp.getData().c_str());
							temp.setData(patternVars.at(varIndex));

							temp.setRight(-1);
							temp.setLeft(-1);

						}
						qs.push_back(temp);

						output=output.substr(1);
						y++;
					}
					
					
					/*
					for(int j=0; j<qs.size(); j++){
						cout<<qs.at(j).data<<endl;
						cout<<"right:"+convertInt(qs.at(j).right)+",left:"+convertInt(qs.at(j).left)<<endl;
					}*/

					//cout<<output<<endl;

					pattern.Expression=qs;
				}else{
				
					if(input!="_"){
						Pattern_node ex;
						ex.setData(input);
						pattern.Expression.push_back(ex);
					}
				}

				


				queries.patternQueries.push_back(pattern);
				
				

	

			}else if(tempName=="with"){
				compareQuery_t compare;

				temp=temp.substr(p+1);
				temp=trim(temp);

				vector<string> subWith;
				explode(temp,"=",&subWith);

				temp=subWith.at(0);
				temp=trim(temp);
                //temp=filterQuote(temp);
                //temp=trim(temp);
								
				p1=temp.find(".");
				if(p1>=0&&p1<100){
					//temp=temp.substr(0,p1);
					temp=trim(temp);
					compare.leftName=temp;
					compare.leftName=trim(convertName(compare.leftName,args));

					if(compare.leftName=="CallProc"){
						//compare.leftName=temp.substr(0,p1);
						toLowerCase(temp);
						compare.leftName=temp;
						compare.leftType="CallProc";
					}else{
						compare.leftType=args[compare.leftName];
					}
					
					if(compare.leftType=="Stmt"||compare.leftType=="Prog_line"){
						compare.leftType="Statement";
					}

				}else{
					if (is_digit(temp[0])){
						compare.leftName=temp;
						compare.leftType="Integer";
					}else{
						if(temp.substr(0,1)=="\""){
							compare.leftName=filterQuote(temp);
							compare.leftType="String";
						}else{
							compare.leftName=temp;
							compare.leftType=args[temp];
						}
					}
				}

				//check sync
				if(compare.leftType=="Call"||compare.leftType=="CallProc"){
					string syncItem=splitString(compare.leftName,0);
					
					if(sync.find(syncItem)!=sync.end()){
						
						queries.callRelation.push_back(syncItem);
					}
				}

				temp=subWith.at(1);
				temp=trim(temp);
                //temp=filterQuote(temp);
                //temp=trim(temp);
				p1=temp.find(".");
				if(p1>=0&&p1<100){
					//temp=temp.substr(0,p1);
					temp=trim(temp);
					compare.rightName=temp;
					compare.rightName=trim(convertName(compare.rightName,args));
					
					if(compare.rightName=="CallProc"){
						//compare.rightName=temp.substr(0,p1);
						toLowerCase(temp);
						compare.rightName=temp;
						compare.rightType="CallProc";
					}else{
						compare.rightType=args[compare.rightName];
					}

					if(compare.rightType=="Stmt"||compare.rightType=="Prog_line"){
						compare.rightType="Statement";
					}

				}else{
					if (is_digit(temp[0])){
						compare.rightName=temp;
						compare.rightType="Integer";
					}else{
						if(temp.substr(0,1)=="\""){
							compare.rightName=filterQuote(temp);
							compare.rightType="String";
						}else{
							compare.rightName=temp;
							compare.rightType=args[temp];
						}
					}
				}


				
				//check sync
				if(compare.rightType=="Call"||compare.rightType=="CallProc"){
					string syncItem=splitString(compare.rightName,0);
					
					if(sync.find(syncItem)!=sync.end()){
						
						queries.callRelation.push_back(syncItem);
					}
				}


				//cout<<"with: =============="<<endl;
				//cout<<compare.leftType+","+compare.leftName+","+compare.rightType+","+compare.rightName<<endl;
				queries.compareQueries.push_back(compare);
			}
		}
	}
	return true;

}



// Query Preprocessor funtions for building table
void QueryProcessor::buildTable(){
	if(queries.selectQuery.SelectType != "Boolean")
		buildSelect(queries.selectQuery);

	for(int i=0;i<queries.funcQueries.size();i++){
		// Query Follows
		if(queries.funcQueries.at(i).FunctionType == "follows")
			queryFollows(queries.funcQueries.at(i));
		// Query Follows*
		else if(queries.funcQueries.at(i).FunctionType == "follows*")
			queryFollowsStar(queries.funcQueries.at(i));
		// Query Parent
		else if(queries.funcQueries.at(i).FunctionType == "parent")
			queryParent(queries.funcQueries.at(i));
		// Query Parent*
		else if(queries.funcQueries.at(i).FunctionType == "parent*")
			queryParentStar(queries.funcQueries.at(i));
		// Query Modifies
		else if(queries.funcQueries.at(i).FunctionType== "modifies")
			queryModifies(queries.funcQueries.at(i));
		// Query Uses
		else if(queries.funcQueries.at(i).FunctionType == "uses")
			queryUses(queries.funcQueries.at(i));
		// Call
		else if(queries.funcQueries.at(i).FunctionType == "calls")
			queryCall(queries.funcQueries.at(i));
		else if(queries.funcQueries.at(i).FunctionType == "calls*")
			queryCallStar(queries.funcQueries.at(i));
		// Next
		else if(queries.funcQueries.at(i).FunctionType == "next")
			queryNext(queries.funcQueries.at(i));
		// Next*
		else if(queries.funcQueries.at(i).FunctionType == "next*"){
			if((*pkb).getNextStarList().empty())
				computeNextStar();
			queryNextStar(queries.funcQueries.at(i));
		}
		// NextBip
		else if(queries.funcQueries.at(i).FunctionType == "nextbip")
			queryNextBip(queries.funcQueries.at(i));
		// NextBip*
		else if(queries.funcQueries.at(i).FunctionType == "nextbip*"){
			if((*pkb).getNextStarMatrix().empty())
				computeNextStar();
			if((*pkb).getNextBipStarList().empty())
				computeNextBipStar();
			queryNextBipStar(queries.funcQueries.at(i));
		}
		// Affects
		else if(queries.funcQueries.at(i).FunctionType == "affects"){
			if((*pkb).getAffectsMatrix().empty())
				computeAffects();
			queryAffects(queries.funcQueries.at(i));
		}
		// Affects*
		else if(queries.funcQueries.at(i).FunctionType == "affects*"){
			if((*pkb).getAffectsMatrix().empty())
				computeAffects();
			if((*pkb).getAffectsStarMatrix().empty())
				computeAffectsStar();
			queryAffectsStar(queries.funcQueries.at(i));
		}
		// AffectsBip
		else if(queries.funcQueries.at(i).FunctionType == "affectsbip"){
			if(!affectsBip.IsAffectsBipComputed())
				affectsBip.ComputeAffectsBip();
			queryAffectsBip(queries.funcQueries.at(i));
		}
		// Affects*
		else if(queries.funcQueries.at(i).FunctionType == "affectsbip*"){
			if(!affectsBip.IsAffectsBipComputed())
				affectsBip.ComputeAffectsBip();
			if(!affectsBip.IsAffectsBipStarComputed())
				affectsBip.ComputeAffectsBipStar();
			queryAffectsBipStar(queries.funcQueries.at(i));
		}
		// Contains
		else if(queries.funcQueries.at(i).FunctionType == "contains") {
			queryContains(queries.funcQueries.at(i));
		}
		// Contains*
		else if(queries.funcQueries.at(i).FunctionType == "contains*") {
			queryContainsStar(queries.funcQueries.at(i));
		}
	}

	// Query Pattern
	for(int i=0;i<queries.patternQueries.size();i++)
		queryPattern(queries.patternQueries.at(i));
	
	// Query comparison
	for(int i=0;i<queries.compareQueries.size();i++)
		queryCompare(queries.compareQueries.at(i));

	// Call stmt# and procName relationship
	for(int i=0;i<queries.callRelation.size();i++)
		buildCallRelationTable(queries.callRelation.at(i));
}

void QueryProcessor::buildSelect(selectQuery_t q){
	AST ast = (*pkb).getAST();
	StmtTable st = (*pkb).getStmtTable();
	VarTable varTable = (*pkb).getVarTable();
	ProcTable procTable = (*pkb).getProcTable();
	ConstTable contTable = (*pkb).getConstTable();
	vector<int> callProc = (*pkb).getCalleeList();

	// Tuple
	if(q.SelectType == "tuple"){
		for(int i=0;i<q.tupleName.size();i++){
			queryTreeNode_t qtNode;
			qtNode.type = "Select";
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.tupleName.at(i));

			vector<int> col1;
			if(q.tupleType.at(i) == "Procedure"){
				for(int j=0;j<procTable.getSize();j++)
					col1.push_back(j);
			}
			else if(q.SelectType == "CallProc"){
				for(int i=0;i<callProc.size();i++)
					col1.push_back(callProc.at(i));
			}
			else if(q.SelectType == "Constant"){
				for(int i=0;i<contTable.getSize();i++)
					col1.push_back(contTable.getConstant(i));
			}
			else if(q.tupleType.at(i) == "Variable"){
				for(int j=0;j<varTable.getSize();j++)
					col1.push_back(j);
			}
			else if(q.tupleType.at(i) == "StmtLst"){
				StmtLstTable slt = (*pkb).getStmtLstTable();
				for(int j=0;j<slt.getSize();j++)
					col1.push_back(slt.getStartLine(j));
			}
			else if(q.tupleType.at(i) == "+"){
				PlusTable pt = (*pkb).getPlusTable();
				for(int j=0;j<pt.getSize();j++)
					col1.push_back(pt.getPlus(j));
			}
			else if(q.tupleType.at(i) == "-"){
				MinusTable mt = (*pkb).getMinusTable();
				for(int j=0;j<mt.getSize();j++)
					col1.push_back(mt.getMinus(j));
			}
			else if(q.tupleType.at(i) == "*"){
				TimesTable tt = (*pkb).getTimesTable();
				for(int j=0;j<tt.getSize();j++)
					col1.push_back(tt.getTimes(j));
			}
			else  if(q.tupleType.at(i) == "Statement"){
				for(int j=1;j<=ast.getTotalLineNum();j++)
					col1.push_back(j);
			}
			else{
				for(int j=1;j<=ast.getTotalLineNum();j++)
					if(q.tupleType.at(i) == st.getLineDetails(j).type)
						col1.push_back(j);
			}
			qtNode.table.push_back(col1);
			queryTree.push_back(qtNode);
		}
	}
	// Not tuple
	else{
		queryTreeNode_t qtNode;
		qtNode.type = "Select";
		qtNode.numOfColumn = 1;
		qtNode.colName.push_back(q.SelectName);

		vector<int> col1;
		if(q.SelectType == "Procedure"){
			for(int i=0;i<procTable.getSize();i++)
				col1.push_back(i);
		}
		else if(q.SelectType == "CallProc"){
			for(int i=0;i<callProc.size();i++)
				col1.push_back(callProc.at(i));
		}
		else if(q.SelectType == "Constant"){
			for(int i=0;i<contTable.getSize();i++)
				col1.push_back(contTable.getConstant(i));
		}
		else if(q.SelectType == "Variable"){
			for(int i=0;i<varTable.getSize();i++)
				col1.push_back(i);
		}
		else if(q.SelectType == "StmtLst"){
			StmtLstTable slt = (*pkb).getStmtLstTable();
			for(int i=0;i<slt.getSize();i++)
				col1.push_back(slt.getStartLine(i));
		}
		else if(q.SelectType == "+"){
			PlusTable pt = (*pkb).getPlusTable();
			for(int i=0;i<pt.getSize();i++)
				col1.push_back(pt.getPlus(i));
		}
		else if(q.SelectType == "-"){
			MinusTable mt = (*pkb).getMinusTable();
			for(int i=0;i<mt.getSize();i++)
				col1.push_back(mt.getMinus(i));
		}
		else if(q.SelectType == "*"){
			TimesTable tt = (*pkb).getTimesTable();
			for(int i=0;i<tt.getSize();i++)
				col1.push_back(tt.getTimes(i));
		}
		else  if(q.SelectType == "Statement"){
			for(int i=1;i<=ast.getTotalLineNum();i++)
				col1.push_back(i);
		}
		else{
			for(int i=1;i<=ast.getTotalLineNum();i++)
				if(q.SelectType == st.getLineDetails(i).type)
					col1.push_back(i);
		}

		qtNode.table.push_back(col1);
		queryTree.push_back(qtNode);
	}
}

void QueryProcessor::queryFollows(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Follows";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	vector<pair<int,int>> list = (*pkb).getFollowsList();
	vector<vector<int>> matrix = (*pkb).getFollowsMatrix();

	AST ast = (*pkb).getAST();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.SecondElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1 && q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.FirstElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1 && q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
	}
	// Both arg are not constant.
	else{
		// Both arg are of statement type.
		if(q.FirstElementType.compare("Statement") == 0 && q.SecondElementType.compare("Statement") == 0){
			if(	q.FirstElementName.compare("_") == 0 && q.SecondElementName.compare("_") == 0 || 
				q.FirstElementName.compare(q.SecondElementName) != 0	)
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// First arg is of statement type.
		else if(q.FirstElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Second arg is of statemnt type.
		else if(q.SecondElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Both args are not of the type statement.
		else{
			if(q.FirstElementName.compare(q.SecondElementName) != 0)
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType== (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

void QueryProcessor::queryFollowsStar(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Follows*";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	vector<pair<int,int>> list = (*pkb).getFollowsStarList();
	vector<vector<int>> matrix = (*pkb).getFollowsStarMatrix();

	AST ast = (*pkb).getAST();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.SecondElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1 && q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.FirstElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1 && q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
	}
	// Both arg are not constant.
	else{
		// Both arg are of statement type.
		if(q.FirstElementType.compare("Statement") == 0 && q.SecondElementType.compare("Statement") == 0){
			if(	q.FirstElementName.compare("_") == 0 && q.SecondElementName.compare("_") == 0 || 
				q.FirstElementName.compare(q.SecondElementName) != 0	)
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// First arg is of statement type.
		else if(q.FirstElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Second arg is of statemnt type.
		else if(q.SecondElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Both args are not of the type statement.
		else{
			if(q.FirstElementName.compare(q.SecondElementName) != 0)
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType== (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

void QueryProcessor::queryParent(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Parent";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	vector<pair<int,int>> list = (*pkb).getParentList();
	vector<vector<int>> matrix = (*pkb).getParentMatrix();

	AST ast = (*pkb).getAST();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.SecondElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1 && q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.FirstElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1 && q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
	}
	// Both arg are not constant.
	else{
		// Both arg are of statement type.
		if(q.FirstElementType.compare("Statement") == 0 && q.SecondElementType.compare("Statement") == 0){
			if(	q.FirstElementName.compare("_") == 0 && q.SecondElementName.compare("_") == 0 || 
				q.FirstElementName.compare(q.SecondElementName) != 0	)
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// First arg is of statement type.
		else if(q.FirstElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Second arg is of statemnt type.
		else if(q.SecondElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Both args are not of the type statement.
		else{
			if(q.FirstElementName.compare(q.SecondElementName) != 0)
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType== (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

void QueryProcessor::queryParentStar(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Parent*";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	vector<pair<int,int>> list = (*pkb).getParentStarList();
	vector<vector<int>> matrix = (*pkb).getParentStarMatrix();

	AST ast = (*pkb).getAST();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.SecondElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1 && q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.FirstElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1 && q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
	}
	// Both arg are not constant.
	else{
		// Both arg are of statement type.
		if(q.FirstElementType.compare("Statement") == 0 && q.SecondElementType.compare("Statement") == 0){
			if(	q.FirstElementName.compare("_") == 0 && q.SecondElementName.compare("_") == 0 || 
				q.FirstElementName.compare(q.SecondElementName) != 0	)
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// First arg is of statement type.
		else if(q.FirstElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Second arg is of statemnt type.
		else if(q.SecondElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Both args are not of the type statement.
		else{
			if(q.FirstElementName.compare(q.SecondElementName) != 0)
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType== (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

void QueryProcessor::queryModifies(funcQuery_t q){
	int firstExp=0;
	int secondExp = 0;
	int emptyTable = 0;
	queryTreeNode_t qtNode;
	qtNode.type = "Modifies";


	vector<pair<int,int>> list = (*pkb).getFullModifiesTable();
	vector<pair<int,int>> procModifiesList = (*pkb).getPModifiesTableV2();
	int totalLineNum = (*pkb).getTotalLineNum();
	ProcTable procTable = (*pkb).getProcTable();

	VarTable varTable = (*pkb).getVarTable();
	AST ast = (*pkb).getAST();

	vector<int> col1, col2;
	// First arg is procedure
	if(q.FirstElementType == "Procedure"){
		// Case Modifies(p,v) || Case Modifies(p,_)
		if(q.SecondElementType == "Variable" || q.SecondElementName == "_"){
			for(int i=0;i<procModifiesList.size();i++){
				col1.push_back(procModifiesList.at(i).first);
				col2.push_back(procModifiesList.at(i).second);
			}
		}
		// Case Modifies(p, "x")
		else{
			for(int i=0;i<procModifiesList.size();i++){
				int v2 = varTable.getVarIndex(q.SecondElementName);
				if(procModifiesList.at(i).second == v2){
					col1.push_back(procModifiesList.at(i).first);
					secondExp = 1;
					col2.push_back(procModifiesList.at(i).second);
				}
			}
		}
	}
	else if(q.FirstElementType == "String"){
		if(q.SecondElementType == "Variable" || q.SecondElementName == "_"){
			for(int i=0;i<procModifiesList.size();i++){
				int p = procTable.getProIndex(q.FirstElementName);
				if(procModifiesList.at(i).first == p){
					col1.push_back(procModifiesList.at(i).first);
					firstExp=1;
					col2.push_back(procModifiesList.at(i).second);
				}
			}
		}
		else{
			for(int i=0;i<procModifiesList.size();i++){
				int v2 = varTable.getVarIndex(q.SecondElementName);
				int p = procTable.getProIndex(q.FirstElementName);
				if(procModifiesList.at(i).first == p && procModifiesList.at(i).second == v2){
					col1.push_back(procModifiesList.at(i).first);
					col2.push_back(procModifiesList.at(i).second);
					firstExp=1;
					secondExp =1;
				}
			}
			if(col1.empty()){
				emptyTable=1;
			}
		}
	}
	// First arg is constant
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		// Case Modifies(1,v)
		if(q.SecondElementType == "Variable"){
			for(int i=0;i<list.size();i++)
				if(list.at(i).first == c1){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		else{
			// Case Modifies(1,_)
			if(q.SecondElementName.compare("_") == 0){
				for(int i=0;i<list.size();i++)
					if(list.at(i).first == c1){
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
			}
			// Case Modifies(1,"x")
			else{
				int v2 = varTable.getVarIndex(q.SecondElementName);
				if(isInList(c1,v2,list)){
					col1.push_back(c1);
					secondExp =1;
					col2.push_back(v2);
				}
			}
		}
	}
	// First arg is not constant.
	else{
		// First arg is statement.
		if(q.FirstElementType.compare("Statement") == 0){
			// Case Modifies(s,v)
			if(q.SecondElementType == "Variable"){
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
			else{
				// Case Modifies(s,_)
				if(q.SecondElementName.compare("_") == 0){
					for(int i=0;i<list.size();i++){
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
				}
				// Case Modifies(s,"x")
				else{
					int v2 = varTable.getVarIndex(q.SecondElementName);
					for(int i=0;i<list.size();i++)
						if(list.at(i).second == v2){
							col1.push_back(list.at(i).first);
							secondExp =1;
							col2.push_back(list.at(i).second);
						}
				}
			}
		}
		// First arg is not statement.
		else{
			// Case Modifies(a/w,v)
			if(q.SecondElementType == "Variable"){
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType.compare((*ast.getNodeFromLineNum(ast.getRoot(),list.at(i).first)).getNodeType()) == 0){	
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
			}
			else{
				// Case Modifies(a/w,_)
				if(q.SecondElementName.compare("_") == 0){
					for(int i=0;i<list.size();i++)
						if(	q.FirstElementType.compare((*ast.getNodeFromLineNum(ast.getRoot(),list.at(i).first)).getNodeType()) == 0){	
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
						}
				}
				// Case Modifies(a/w,"x")
				else{
					int v2 = varTable.getVarIndex(q.SecondElementName);
					for(int i=0;i<list.size();i++)
						if(	q.FirstElementType.compare((*ast.getNodeFromLineNum(ast.getRoot(),list.at(i).first)).getNodeType()) == 0 &&
							list.at(i).second == v2){					
								col1.push_back(list.at(i).first);
								secondExp =1;
								col2.push_back(list.at(i).second);
						}
				}
			}
		}
	}
	if(firstExp==1&&secondExp==1){
	 	qtNode.numOfColumn = 1;
		qtNode.colName.push_back("_"); 
		vector<int> temp = vector<int>();
		if(emptyTable==0){
			temp.push_back(-1);
		}
		qtNode.table.push_back(temp);
	}	
	if(firstExp==1&&secondExp==0){
		qtNode.numOfColumn = 1;
	    qtNode.colName.push_back(q.SecondElementName); 
		qtNode.table.push_back(col2);
	}
	if(firstExp==0&&secondExp==1){
		qtNode.numOfColumn = 1;
	    qtNode.colName.push_back(q.FirstElementName); 
		qtNode.table.push_back(col1);
	}
	if(firstExp==0&&secondExp==0){
		qtNode.numOfColumn = 2;
	    qtNode.colName.push_back(q.FirstElementName);
	    qtNode.colName.push_back(q.SecondElementName);
		qtNode.table.push_back(col1);
	    qtNode.table.push_back(col2);
	}
	
	queryTree.push_back(qtNode);
}

void QueryProcessor::queryUses(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Uses";
	int firstExp=0;
	int secondExp =0;
	int emptyTable =0;

	vector<pair<int,int>> list = (*pkb).getFullUsesTable();
	vector<pair<int,int>> procUsesList = (*pkb).getPUsesTableV2();
	int totalLineNum = (*pkb).getTotalLineNum();

	ProcTable procTable = (*pkb).getProcTable();
	VarTable varTable = (*pkb).getVarTable();
	AST ast = (*pkb).getAST();

	vector<int> col1, col2;
	// First arg is procedure
	if(q.FirstElementType == "Procedure"){
		// Case Uses(p,v) || Case Uses(p,_)
		if(q.SecondElementType == "Variable" || q.SecondElementName == "_"){
			for(int i=0;i<procUsesList.size();i++){
				col1.push_back(procUsesList.at(i).first);
				col2.push_back(procUsesList.at(i).second);
			}
		}
		// Case Uses(p, "x")
		else{
			for(int i=0;i<procUsesList.size();i++){
				int v2 = varTable.getVarIndex(q.SecondElementName);
				if(procUsesList.at(i).second == v2){
					col1.push_back(procUsesList.at(i).first);
					secondExp =1;
					col2.push_back(procUsesList.at(i).second);
				}
			}
		}
	}
	else if(q.FirstElementType == "String"){
		if(q.SecondElementType == "Variable" || q.SecondElementName == "_"){
			for(int i=0;i<procUsesList.size();i++){
				int p = procTable.getProIndex(q.FirstElementName);
				if(procUsesList.at(i).first == p){
					col1.push_back(procUsesList.at(i).first);
					firstExp=1;
					col2.push_back(procUsesList.at(i).second);
				}
			}
		}
		else{
			for(int i=0;i<procUsesList.size();i++){
				int v2 = varTable.getVarIndex(q.SecondElementName);
				int p = procTable.getProIndex(q.FirstElementName);
				if(procUsesList.at(i).first == p && procUsesList.at(i).second == v2){
					col1.push_back(procUsesList.at(i).first);
					firstExp=1;
					secondExp =1;
					col2.push_back(procUsesList.at(i).second);
				}
			}
			if(col1.empty()){
				emptyTable=1;
			}
		}
	}
	// First arg is constant
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		// Case Uses(1,v)
		if(q.SecondElementType == "Variable"){
			for(int i=0;i<list.size();i++)
				if(list.at(i).first == c1){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		else{
			// Case Uses(1,_)
			if(q.SecondElementName.compare("_") == 0){
				for(int i=0;i<list.size();i++)
					if(list.at(i).first == c1){
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
			}
			// Case Uses(1,"x")
			else{
				int c2 = varTable.getVarIndex(q.SecondElementName);
				if(isInList(c1,c2,list)){
					col1.push_back(c1);
					secondExp =1;
					col2.push_back(c2);
				}
			}
		}
	}
	// First arg is not constant.
	else{
		// First arg is statement.
		if(q.FirstElementType.compare("Statement") == 0){
			// Case Uses(s,v)
			if(q.SecondElementType == "Variable"){
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
			else{
				// Case Uses(s,_)
				if(q.SecondElementName.compare("_") == 0){
					for(int i=0;i<list.size();i++){
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
				}
				// Case Uses(s,"x")
				else{
					int c2 = varTable.getVarIndex(q.SecondElementName);
					for(int i=0;i<list.size();i++)
						if(list.at(i).second == c2){
							col1.push_back(list.at(i).first);
							secondExp =1;
							col2.push_back(list.at(i).second);
						}
				}
			}
		}
		// First arg is not statement.
		else{
			// Case Uses(a/w,v)
			if(q.SecondElementType == "Variable"){
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType.compare((*ast.getNodeFromLineNum(ast.getRoot(),list.at(i).first)).getNodeType()) == 0){	
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
			}
			else{
				// Case Uses(a/w,_)
				if(q.SecondElementName.compare("_") == 0){
					for(int i=0;i<list.size();i++)
						if(	q.FirstElementType.compare((*ast.getNodeFromLineNum(ast.getRoot(),list.at(i).first)).getNodeType()) == 0){	
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
						}
				}
				// Case Uses(a/w,"x")
				else{
					int c2 = varTable.getVarIndex(q.SecondElementName);
					for(int i=0;i<list.size();i++)
						if(	q.FirstElementType.compare((*ast.getNodeFromLineNum(ast.getRoot(),list.at(i).first)).getNodeType()) == 0 &&
							list.at(i).second == c2){					
								col1.push_back(list.at(i).first);
								secondExp =1;
								col2.push_back(list.at(i).second);
						}
				}
			}
		}
	}
	if(firstExp==1&&secondExp==1){
	 	qtNode.numOfColumn = 1;
		qtNode.colName.push_back("_"); 
		vector<int> temp = vector<int>();
		if(emptyTable==0){
			temp.push_back(-1);
		}
		qtNode.table.push_back(temp);
	}	
	if(firstExp==1&&secondExp==0){
		qtNode.numOfColumn = 1;
	    qtNode.colName.push_back(q.SecondElementName); 
		qtNode.table.push_back(col2);
	}
	if(firstExp==0&&secondExp==1){
		qtNode.numOfColumn = 1;
	    qtNode.colName.push_back(q.FirstElementName); 
		qtNode.table.push_back(col1);
	}
	if(firstExp==0&&secondExp==0){
		qtNode.numOfColumn = 2;
	    qtNode.colName.push_back(q.FirstElementName);
	    qtNode.colName.push_back(q.SecondElementName);
		qtNode.table.push_back(col1);
	    qtNode.table.push_back(col2);
	}
	
	queryTree.push_back(qtNode);
}

void QueryProcessor::queryCall(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Calls";
	int secondExp=0;
	int firstExp=0;
	int emptyTable = 0;

	vector<int> col1, col2;
	
	Calls calls = (*pkb).getCalls();
	vector<pair<int,int>> list = (*pkb).getCallsList();
	ProcTable procTable = (*pkb).getProcTable();

	if(q.FirstElementType == "Procedure" && q.SecondElementType == "Procedure"){
		for(int i=0;i<list.size();i++){
			col1.push_back(list.at(i).first);
			col2.push_back(list.at(i).second);
		}
	}
	else if(q.FirstElementType == "Procedure"){
		if(q.SecondElementName == "_"){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else{
			for(int i=0;i<list.size();i++){
				string procName = procTable.getProName(list.at(i).second);
				if(procName == q.SecondElementName){
					col1.push_back(list.at(i).first);
					secondExp=1;
					col2.push_back(list.at(i).second);
				}
			}
		}
	}
	else if(q.SecondElementType == "Procedure"){
		if(q.FirstElementName == "_"){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else{
			for(int i=0;i<list.size();i++){
				string procName = procTable.getProName(list.at(i).first);
				if(procName == q.FirstElementName){
					col1.push_back(list.at(i).first);
					firstExp=1;
					col2.push_back(list.at(i).second);
				}
			}
		}
	}
	else{
		if(q.FirstElementName == "_" && q.SecondElementName == "_"){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else if(q.FirstElementName == "_"){
			int proc2Idx = procTable.getProIndex(q.SecondElementName);
			for(int i=0;i<list.size();i++){
				if(list.at(i).second == proc2Idx){
					col1.push_back(list.at(i).first);
					secondExp=1;
					col2.push_back(list.at(i).second);
				}
			}
		}
		else if(q.SecondElementName == "_"){
			int proc1Idx = procTable.getProIndex(q.FirstElementName);
			for(int i=0;i<list.size();i++){
				if(list.at(i).first == proc1Idx){
					col1.push_back(list.at(i).first);
					firstExp=1;
					col2.push_back(list.at(i).second);
				}
			}
		}
		else{
			int procNum1 = procTable.getProIndex(q.FirstElementName), procNum2 = procTable.getProIndex(q.SecondElementName);
			if(calls.isCall(procNum1, procNum2)){
				col1.push_back(procNum1);
				col2.push_back(procNum2);
				firstExp=1;
				secondExp=1;		
			}
			if(col1.empty()){
				emptyTable=1;
			}
		}
	}

	if(firstExp==1&&secondExp==1){
	 	qtNode.numOfColumn = 1;
		qtNode.colName.push_back("_"); 
		vector<int> temp = vector<int>();
		if(emptyTable==0){
			temp.push_back(-1);
		}
		qtNode.table.push_back(temp);
	}	
	if(firstExp==1&&secondExp==0){
		qtNode.numOfColumn = 1;
	    qtNode.colName.push_back(q.SecondElementName); 
		qtNode.table.push_back(col2);
	}
	if(firstExp==0&&secondExp==1){
		qtNode.numOfColumn = 1;
	    qtNode.colName.push_back(q.FirstElementName); 
		qtNode.table.push_back(col1);
	}
	if(firstExp==0&&secondExp==0){
		qtNode.numOfColumn = 2;
	    qtNode.colName.push_back(q.FirstElementName);
	    qtNode.colName.push_back(q.SecondElementName);
		qtNode.table.push_back(col1);
	    qtNode.table.push_back(col2);
	}
	
	queryTree.push_back(qtNode);
}

void QueryProcessor::queryCallStar(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Calls*";
	int secondExp=0;
	int firstExp=0;
	int emptyTable =0;

	vector<int> col1, col2;
	
	Calls calls = (*pkb).getCalls();
	vector<pair<int,int>> list = (*pkb).getCallsStarList();
	ProcTable procTable = (*pkb).getProcTable();

	if(q.FirstElementType == "Procedure" && q.SecondElementType == "Procedure"){
		for(int i=0;i<list.size();i++){
			col1.push_back(list.at(i).first);
			col2.push_back(list.at(i).second);
		}
	}
	else if(q.FirstElementType == "Procedure"){
		if(q.SecondElementName == "_"){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else{
			for(int i=0;i<list.size();i++){
				string procName = procTable.getProName(list.at(i).second);
				if(procName == q.SecondElementName){
					col1.push_back(list.at(i).first);
					secondExp=1;
					col2.push_back(list.at(i).second);
				}
			}
		}
	}
	else if(q.SecondElementType == "Procedure"){
		if(q.FirstElementName == "_"){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else{
			for(int i=0;i<list.size();i++){
				string procName = procTable.getProName(list.at(i).first);
				if(procName == q.FirstElementName){
					col1.push_back(list.at(i).first);
					firstExp=1;
					col2.push_back(list.at(i).second);
				}
			}
		}
	}
	else{
		if(q.FirstElementName == "_" && q.SecondElementName == "_"){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else if(q.FirstElementName == "_"){
			int proc2Idx = procTable.getProIndex(q.SecondElementName);
			for(int i=0;i<list.size();i++){
				if(list.at(i).second == proc2Idx){
					col1.push_back(list.at(i).first);
					secondExp=1;
					col2.push_back(list.at(i).second);
				}
			}
		}
		else if(q.SecondElementName == "_"){
			int proc1Idx = procTable.getProIndex(q.FirstElementName);
			for(int i=0;i<list.size();i++){
				if(list.at(i).first == proc1Idx){
					col1.push_back(list.at(i).first);
					firstExp=1;
					col2.push_back(list.at(i).second);
				}
			}
		}
		else{
			int procNum1 = procTable.getProIndex(q.FirstElementName), procNum2 = procTable.getProIndex(q.SecondElementName);
			if(calls.isCall(procNum1, procNum2)){
				col1.push_back(procNum1);
				col2.push_back(procNum2);
				firstExp=1;
				secondExp=1;
			}
			if(col1.empty()){
				emptyTable=1;
			}
		}
	}

	if(firstExp==1&&secondExp==1){
	 	qtNode.numOfColumn = 1;
		qtNode.colName.push_back("_"); 
		vector<int> temp = vector<int>();
		if(emptyTable==0){
			temp.push_back(-1);
		}
		qtNode.table.push_back(temp);
	}	
	if(firstExp==1&&secondExp==0){
		qtNode.numOfColumn = 1;
	    qtNode.colName.push_back(q.SecondElementName); 
		qtNode.table.push_back(col2);
	}
	if(firstExp==0&&secondExp==1){
		qtNode.numOfColumn = 1;
	    qtNode.colName.push_back(q.FirstElementName); 
		qtNode.table.push_back(col1);
	}
	if(firstExp==0&&secondExp==0){
		qtNode.numOfColumn = 2;
	    qtNode.colName.push_back(q.FirstElementName);
	    qtNode.colName.push_back(q.SecondElementName);
		qtNode.table.push_back(col1);
	    qtNode.table.push_back(col2);
	}
	
	queryTree.push_back(qtNode);
}
// Next
void QueryProcessor::queryNext(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Next";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	vector<pair<int,int>> list = (*pkb).getNextList();
	vector<vector<int>> matrix = (*pkb).getNextMatrix();

	AST ast = (*pkb).getAST();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.SecondElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1 && q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.FirstElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1 && q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
	}
	// Both arg are not constant.
	else{
		// Both arg are of statement type.
		if(q.FirstElementType.compare("Statement") == 0 && q.SecondElementType.compare("Statement") == 0){
			if(q.FirstElementName == "_" && q.SecondElementName == "_" || q.FirstElementName != q.SecondElementName){
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
			else{
				for(int i=0;i<list.size();i++){ 
					if(list.at(i).first == list.at(i).second){
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
				}
			}
		}
		// First arg is of statement type.
		else if(q.FirstElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Second arg is of statemnt type.
		else if(q.SecondElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Both args are not of the type statement.
		else{
			if(q.FirstElementName == q.SecondElementName){
				for(int i=0;i<list.size();i++)
					if(	list.at(i).first == list.at(i).second &&
						q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
			}
			else{
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType== (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
			}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// Next*
void QueryProcessor::computeNextStar(){
	StmtTable st = (*pkb).getStmtTable();
	int totalLineNum = (*pkb).getTotalLineNum();

	vector<vector<int>> nextStarMatrix(totalLineNum+1, vector<int>(totalLineNum+1, 0));
	vector<pair<int, int>> nextStarList;

	vector<while_t> wTable = st.getWhileTable();
	vector<if_t> iTable = st.getIfTable();

	for(int i=1;i<=totalLineNum;i++)
		for(int j=1;j<=totalLineNum;j++)
			if(st.getLineDetails(i).procNum == st.getLineDetails(j).procNum && i<j) 
				nextStarMatrix.at(i).at(j) = 1;
	for(int k=0;k<iTable.size();k++)
		for(int i=iTable.at(k).thenStartLine;i<=iTable.at(k).thenEndLine;i++)
			for(int j=iTable.at(k).elseStartLine;j<=iTable.at(k).elseEndLine;j++)
				nextStarMatrix.at(i).at(j) = 0;
	for(int k=0;k<wTable.size();k++)
		for(int i=wTable.at(k).lineNum;i<=wTable.at(k).loopEndLine;i++)
			for(int j=wTable.at(k).lineNum;j<=wTable.at(k).loopEndLine;j++)
				nextStarMatrix.at(i).at(j) = 1;

	for(int i=1;i<=totalLineNum;i++)
		for(int j=1;j<=totalLineNum;j++)
			if(nextStarMatrix.at(i).at(j) == 1)
				nextStarList.push_back(pair<int, int>(i, j));

	(*pkb).setNextStarList(nextStarList);
	(*pkb).setNextStarMatrix(nextStarMatrix);
}
void QueryProcessor::queryNextStar(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Next*";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	vector<pair<int,int>> list = (*pkb).getNextStarList();
	vector<vector<int>> matrix = (*pkb).getNextStarMatrix();

	AST ast = (*pkb).getAST();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.SecondElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1 && q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.FirstElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1 && q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
	}
	// Both arg are not constant.
	else{
		// Both arg are of statement type.
		if(q.FirstElementType.compare("Statement") == 0 && q.SecondElementType.compare("Statement") == 0){
			if(q.FirstElementName == "_" && q.SecondElementName == "_" || q.FirstElementName != q.SecondElementName){
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
			else{
				for(int i=0;i<list.size();i++){ 
					if(list.at(i).first == list.at(i).second){
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
				}
			}
		}
		// First arg is of statement type.
		else if(q.FirstElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Second arg is of statemnt type.
		else if(q.SecondElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Both args are not of the type statement.
		else{
			if(q.FirstElementName == q.SecondElementName){
				for(int i=0;i<list.size();i++)
					if(	list.at(i).first == list.at(i).second &&
						q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
			}
			else{
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType== (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
			}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// NextBip
void QueryProcessor::queryNextBip(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Next";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	vector<pair<int,int>> list = (*pkb).getNextBipList();
	vector<vector<int>> matrix = (*pkb).getNextBipMatrix();

	AST ast = (*pkb).getAST();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.SecondElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1 && q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.FirstElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1 && q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
	}
	// Both arg are not constant.
	else{
		// Both arg are of statement type.
		if(q.FirstElementType.compare("Statement") == 0 && q.SecondElementType.compare("Statement") == 0){
			if(q.FirstElementName == "_" && q.SecondElementName == "_" || q.FirstElementName != q.SecondElementName){
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
			else{
				for(int i=0;i<list.size();i++){ 
					if(list.at(i).first == list.at(i).second){
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
				}
			}
		}
		// First arg is of statement type.
		else if(q.FirstElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Second arg is of statemnt type.
		else if(q.SecondElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Both args are not of the type statement.
		else{
			if(q.FirstElementName == q.SecondElementName){
				for(int i=0;i<list.size();i++)
					if(	list.at(i).first == list.at(i).second &&
						q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
			}
			else{
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType== (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
			}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// NextBip*
/*void QueryProcessor::computeNextBipStar(){
	StmtTable st = (*pkb).getStmtTable();
	int totalLineNum = (*pkb).getTotalLineNum();
	vector<Triple> calls = (*pkb).getCalls().getCalls();
	vector<int> sortedCalls = (*pkb).getSortedCall();
	vector<bool> callsProcessed(calls.size(), false);
	ProcTable pt = (*pkb).getProcTable();

	vector<vector<int>> nextStarMatrix = (*pkb).getNextStarMatrix(), temp(nextStarMatrix), nextBipStarMatrix(nextStarMatrix);
	vector<pair<int, int>> nextBipStarList((*pkb).getNextStarList());

	for(int i=0;i<sortedCalls.size();i++){
		int index = sortedCalls.at(i);
		if(callsProcessed.at(index)) continue;

		callsProcessed.at(index) = true;
		int line = calls.at(index).getFirst(), proc = calls.at(index).getThird();
		int procStart = pt.getProStartLine(proc), procEnd = pt.getProcEndLine(proc);
		
		for(int k=procStart;k<=procEnd;k++){
			if(nextBipStarMatrix.at(line).at(k) == 0)
				nextBipStarList.push_back(pair<int,int>(line,k));
			nextBipStarMatrix.at(line).at(k) = 1;
			temp.at(line).at(k) = 1;
		}

		for(int j=1;j<=totalLineNum;j++){
			if(temp.at(j).at(line) == 1){
				for(int k=procStart;k<=procEnd;k++){
					if(nextBipStarMatrix.at(j).at(k) == 0)
						nextBipStarList.push_back(pair<int,int>(j,k));
					nextBipStarMatrix.at(j).at(k) = 1;
					temp.at(j).at(k) = 1;
				}
			}
		}
	}

	callsProcessed = vector<bool>(calls.size(), false);
	temp = vector<vector<int>>(nextStarMatrix);
	for(int i=0;i<sortedCalls.size();i++){
		int index = sortedCalls.at(i);
		if(callsProcessed.at(index)) continue;

		callsProcessed.at(index) = true;
		int line = calls.at(index).getFirst(), proc = calls.at(index).getThird();
		int procStart = pt.getProStartLine(proc), procEnd = pt.getProcEndLine(proc);

		for(int j=1;j<=totalLineNum;j++){
			if(temp.at(line).at(j) == 1){
				for(int k=procStart;k<=procEnd;k++){
					if(nextBipStarMatrix.at(k).at(j) == 0)
						nextBipStarList.push_back(pair<int,int>(k,j));
					nextBipStarMatrix.at(k).at(j) = 1;
					temp.at(k).at(j) = 1;
				}
			}
		}
	}
	/*
	for(int i=1;i<=totalLineNum;i++){
		for(int j=1;j<=totalLineNum;j++)
			if(nextBipStarMatrix.at(i).at(j) == 1)
				nextBipStarList.push_back(pair<int,int>(i,j));
	}
	
	(*pkb).setNextBipStarList(nextBipStarList);
	(*pkb).setNextBipStarMatrix(nextBipStarMatrix);
}*/

void QueryProcessor::computeNextBipStar(){
	vector<vector<int>> BipSeq = (*pkb).getExtendProcedure();
	vector<int> curProcCalls, nextProcCalls;
	Calls calls = (*pkb).getCalls();
	StmtTable st = (*pkb).getStmtTable();
	ProcTable pt = (*pkb).getProcTable();
	int totalLineNum = (*pkb).getTotalLineNum();

	vector<vector<int>> nextBipStarMatrix((*pkb).getNextStarMatrix());
	vector<pair<int,int>> nextBipStarList((*pkb).getNextStarList());

	for(int n=0;n<BipSeq.size();n++){
		int curProc = st.getLineDetails(BipSeq.at(n).at(0)).procNum;
		vector<int> callLines = calls.getLineNum(curProc);
		curProcCalls.insert(curProcCalls.end(), callLines.begin(), callLines.end());

		while(!curProcCalls.empty()){
			for(int i=0;i<curProcCalls.size();i++){
				int line = curProcCalls.at(i), proc = calls.getCalleeFromLineNum(line);
				int procStart = pt.getProStartLine(proc), procEnd = pt.getProcEndLine(proc);

				// Lines can reach this call
				for(int j=1;j<=totalLineNum;j++){
					if(nextBipStarMatrix.at(j).at(line) == 1){
						for(int k=procStart;k<=procEnd;k++){
							if(nextBipStarMatrix.at(j).at(k) == 0)
								nextBipStarList.push_back(pair<int,int>(j,k));
							nextBipStarMatrix.at(j).at(k) = 1;
						}
					}
				}
			}
			for(int i=0;i<curProcCalls.size();i++){
				int line = curProcCalls.at(i), proc = calls.getCalleeFromLineNum(line);
				int procStart = pt.getProStartLine(proc), procEnd = pt.getProcEndLine(proc);

				// Lines this call can reach
				for(int j=1;j<=totalLineNum;j++){
					if(nextBipStarMatrix.at(line).at(j) == 1){
						for(int k=procStart;k<=procEnd;k++){
							if(nextBipStarMatrix.at(k).at(j) == 0)
								nextBipStarList.push_back(pair<int,int>(k,j));
							nextBipStarMatrix.at(k).at(j) = 1;
						}
					}
				}

				// this call can reach lines in called procedure
				for(int k=procStart;k<=procEnd;k++){
					if(nextBipStarMatrix.at(line).at(k) == 0)
						nextBipStarList.push_back(pair<int,int>(line,k));
					nextBipStarMatrix.at(line).at(k) = 1;
				}

				// Prepare call in next level
				vector<int> callLinesInCallee = calls.getLineNum(proc);
				nextProcCalls.insert(nextProcCalls.end(), callLinesInCallee.begin(), callLinesInCallee.end());
			}
			curProcCalls.clear();
			curProcCalls = vector<int>(nextProcCalls);
			nextProcCalls.clear();
		}
	}
	(*pkb).setNextBipStarMatrix(nextBipStarMatrix);
	(*pkb).setNextStarList(nextBipStarList);
}
void QueryProcessor::queryNextBipStar(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Next*";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	vector<pair<int,int>> list = (*pkb).getNextBipStarList();
	vector<vector<int>> matrix = (*pkb).getNextBipStarMatrix();

	AST ast = (*pkb).getAST();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.SecondElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(c1).at(i) == 1 && q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(c1);
					col2.push_back(i);
				}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(q.FirstElementType.compare("Statement") == 0){
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
		else{
			for(int i=1;i<=totalLineNum;i++)
				if(matrix.at(i).at(c2) == 1 && q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), i)).getNodeType()){
					col1.push_back(i);
					col2.push_back(c2);
				}
		}
	}
	// Both arg are not constant.
	else{
		// Both arg are of statement type.
		if(q.FirstElementType.compare("Statement") == 0 && q.SecondElementType.compare("Statement") == 0){
			if(q.FirstElementName == "_" && q.SecondElementName == "_" || q.FirstElementName != q.SecondElementName){
				for(int i=0;i<list.size();i++){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
			else{
				for(int i=0;i<list.size();i++){ 
					if(list.at(i).first == list.at(i).second){
						col1.push_back(list.at(i).first);
						col2.push_back(list.at(i).second);
					}
				}
			}
		}
		// First arg is of statement type.
		else if(q.FirstElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Second arg is of statemnt type.
		else if(q.SecondElementType.compare("Statement") == 0){
			for(int i=0;i<list.size();i++)
				if(q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType()){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
		}
		// Both args are not of the type statement.
		else{
			if(q.FirstElementName == q.SecondElementName){
				for(int i=0;i<list.size();i++)
					if(	list.at(i).first == list.at(i).second &&
						q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
			}
			else{
				for(int i=0;i<list.size();i++)
					if(	q.FirstElementType == (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).first)).getNodeType() && 
						q.SecondElementType== (*ast.getNodeFromLineNum(ast.getRoot(), list.at(i).second)).getNodeType()){
							col1.push_back(list.at(i).first);
							col2.push_back(list.at(i).second);
					}
			}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// Affects
void QueryProcessor::computeAffects(){
	Affects af = Affects(pkb);
	(*pkb).setAffectsMatrix(af.ComputeAffects());
	(*pkb).setAffectsList(af.GetAffectsList());
}
void QueryProcessor::queryAffects(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Affects";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	StmtTable st = (*pkb).getStmtTable();

	vector<pair<int,int>> list = (*pkb).getAffectsList();
	vector<vector<int>> matrix = (*pkb).getAffectsMatrix();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c1).type != "Assign" || st.getLineDetails(c2).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c1).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		for(int i=1;i<=totalLineNum;i++){
			if(matrix.at(c1).at(i) == 1){
				col1.push_back(c1);
				col2.push_back(i);
			}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c2).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		for(int i=1;i<=totalLineNum;i++){
			if(matrix.at(i).at(c2) == 1){
				col1.push_back(i);
				col2.push_back(c2);
			}
		}
	}
	// Both arg are not constant.
	else{
		if(q.FirstElementName == "_" && q.SecondElementName == "_" || q.FirstElementName != q.SecondElementName){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else{
			for(int i=0;i<list.size();i++){ 
				if(list.at(i).first == list.at(i).second){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// Affect*
void QueryProcessor::computeAffectsStar(){
	int totalLineNum =(*pkb).getTotalLineNum();
	
	vector<vector<int>> affectsStarMatrix((*pkb).getAffectsMatrix());
	vector<pair<int,int>> affectsStarList((*pkb).getAffectsList());
	StmtTable stmtTable = (*pkb).getStmtTable();

	for(int i=1;i<=totalLineNum;i++){
		for(int j=1;j<=totalLineNum;j++)
			if(affectsStarMatrix.at(i).at(j) == 0 && stmtTable.getLineDetails(i).procNum == stmtTable.getLineDetails(j).procNum){
				for(int k=1;k<=totalLineNum;k++)
					if(affectsStarMatrix.at(i).at(k) == 1 && affectsStarMatrix.at(k).at(j) == 1){
						affectsStarList.push_back(pair<int,int>(i,j));
						affectsStarMatrix.at(i).at(j) = 1;
					}
			}
	}
	(*pkb).setAffectsStarList(affectsStarList);
	(*pkb).setAffectsStarMatrix(affectsStarMatrix);
}
void QueryProcessor::queryAffectsStar(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Affects*";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	StmtTable st = (*pkb).getStmtTable();

	vector<pair<int,int>> list = (*pkb).getAffectsStarList();
	vector<vector<int>> matrix = (*pkb).getAffectsStarMatrix();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c1).type != "Assign" || st.getLineDetails(c2).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c1).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		for(int i=1;i<=totalLineNum;i++){
			if(matrix.at(c1).at(i) == 1){
				col1.push_back(c1);
				col2.push_back(i);
			}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c2).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		for(int i=1;i<=totalLineNum;i++){
			if(matrix.at(i).at(c2) == 1){
				col1.push_back(i);
				col2.push_back(c2);
			}
		}
	}
	// Both arg are not constant.
	else{
		if(q.FirstElementName == "_" && q.SecondElementName == "_" || q.FirstElementName != q.SecondElementName){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else{
			for(int i=0;i<list.size();i++){ 
				if(list.at(i).first == list.at(i).second){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// AffectsBip
void QueryProcessor::queryAffectsBip(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Affects";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	StmtTable st = (*pkb).getStmtTable();
	
	vector<vector<int>> matrix = affectsBip.GetAffectsBipMatrix();
	vector<pair<int,int>> list = affectsBip.GetAffectsBipList();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c1).type != "Assign" || st.getLineDetails(c2).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c1).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		for(int i=1;i<=totalLineNum;i++){
			if(matrix.at(c1).at(i) == 1){
				col1.push_back(c1);
				col2.push_back(i);
			}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c2).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		for(int i=1;i<=totalLineNum;i++){
			if(matrix.at(i).at(c2) == 1){
				col1.push_back(i);
				col2.push_back(c2);
			}
		}
	}
	// Both arg are not constant.
	else{
		if(q.FirstElementName == "_" && q.SecondElementName == "_" || q.FirstElementName != q.SecondElementName){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else{
			for(int i=0;i<list.size();i++){ 
				if(list.at(i).first == list.at(i).second){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// AffectsBip*
void QueryProcessor::queryAffectsBipStar(funcQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Affect*";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	vector<int> col1, col2;

	int totalLineNum = (*pkb).getTotalLineNum();
	StmtTable st = (*pkb).getStmtTable();

	vector<vector<int>> matrix = affectsBip.GetAffectsBipStarMatrix();
	vector<pair<int,int>> list = affectsBip.GetAffectsBipStarList();

	// Both args are constant.
	if(q.FirstElementType.compare("Constant") == 0 && q.SecondElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str()), c2 = atoi(q.SecondElementName.c_str());
		if(c1>totalLineNum || c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c1).type != "Assign" || st.getLineDetails(c2).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		if(matrix.at(c1).at(c2) == 1){
			col1.push_back(c1);
			col2.push_back(c2);	
		}
	}
	// First arg is constant.
	else if(q.FirstElementType.compare("Constant") == 0){
		int c1 = atoi(q.FirstElementName.c_str());
		if(c1>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c1).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		for(int i=1;i<=totalLineNum;i++){
			if(matrix.at(c1).at(i) == 1){
				col1.push_back(c1);
				col2.push_back(i);
			}
		}
	}
	// Second arg is constant.
	else if(q.SecondElementType.compare("Constant") == 0){
		int c2 = atoi(q.SecondElementName.c_str());
		if(c2>totalLineNum){
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
			queryTree.push_back(qtNode);
			return;
		}
		if(st.getLineDetails(c2).type != "Assign"){
			cout << "Affects need to query on assign." << endl;
			return;
		}
		for(int i=1;i<=totalLineNum;i++){
			if(matrix.at(i).at(c2) == 1){
				col1.push_back(i);
				col2.push_back(c2);
			}
		}
	}
	// Both arg are not constant.
	else{
		if(q.FirstElementName == "_" && q.SecondElementName == "_" || q.FirstElementName != q.SecondElementName){
			for(int i=0;i<list.size();i++){
				col1.push_back(list.at(i).first);
				col2.push_back(list.at(i).second);
			}
		}
		else{
			for(int i=0;i<list.size();i++){ 
				if(list.at(i).first == list.at(i).second){
					col1.push_back(list.at(i).first);
					col2.push_back(list.at(i).second);
				}
			}
		}
	}
	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// Contains
bool isConstant(string str){
	
	stringstream convert(str);
	int result;
	if(convert>>result)
	{
		return true;
	}
    return false;
}

bool isOperation(string str) {
	if ((str.compare("+")==0) || (str.compare("-")==0) || (str.compare("*")==0)) {
		return true;
	}
	return false;
}

bool isStatement(string str) {
	if ((str.compare("Assign")==0) || (str.compare("While")==0) || 
		(str.compare("If")==0) || (str.compare("Call")==0)) {
		return true;
	}
	return false;
}


void QueryProcessor::queryContains(funcQuery_t q) {
	queryTreeNode_t qtNode;
	qtNode.type = "Contains";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	Contains contains = (*pkb).getContains();
	ProcTable procTable = (*pkb).getProcTable();
	ConstTable consTable = (*pkb).getConstTable();
	VarTable varTable = (*pkb).getVarTable();
	StmtLstTable stmtLstTable = (*pkb).getStmtLstTable();
	PlusTable plusTable = (*pkb).getPlusTable();
	MinusTable minusTable = (*pkb).getMinusTable();
	TimesTable timesTable = (*pkb).getTimesTable();
	vector<int> col1, col2;

	vector<TNode> output; // record all the possible TNode for second arg
	//compute all the possible TNode for second arg first
	if (q.SecondElementType=="String"){
		if (isConstant(q.SecondElementName)) {
			int c2 = atoi(q.SecondElementName.c_str());
			int index = consTable.getConIndex(c2);
			output = contains.searchByIndex("Constant", index);
		} else if (isOperation(q.SecondElementName)) {
			output = contains.searchByType(q.SecondElementName);
		} else if (procTable.getProIndex(q.SecondElementName)!=-1) {
			int index = procTable.getProIndex(q.SecondElementName);
			output = contains.searchByIndex("Procedure", index);
		} else if (varTable.getVarIndex(q.SecondElementName)!=-1) {
			int index = varTable.getVarIndex(q.SecondElementName);
			output = contains.searchByIndex("Variable", index);
		}
	} else if (q.SecondElementType == "Integer") {
		int c2 = atoi(q.SecondElementName.c_str());
		output = contains.searchByProcline(c2);
	} else if (q.SecondElementType == "StmtLst") {
		output = contains.searchByType("StmtLst");
	} else if (q.SecondElementName == "_") {
		output = contains.getList();
	} else if (q.SecondElementType == "Statement") {
		vector<TNode> list = contains.getList();
		for (int i=0; i<list.size(); i++) {
			TNode temp = list.at(i);
			if (isStatement(temp.getNodeType())) {
				output.push_back(temp);
			}
		}
	} else if (q.SecondElementType == "Procedure") {
		output = contains.searchByType("Procedure");
	} else if (q.SecondElementType == "Variable") {
		output = contains.searchByType("Variable");
	} else if (q.SecondElementType == "Constant") {
		output = contains.searchByType("Constant");
	} else if (isStatement(q.SecondElementType)) {
		output = contains.searchByType(q.SecondElementType);
	} else if (isOperation(q.SecondElementType)) {
		output = contains.searchByType(q.SecondElementType);
	}

	//compute the result based on the output of second arg
	if (q.FirstElementType == "String") {
		if (isOperation(q.FirstElementName)) {
			for (int i=0; i<output.size(); i++) {
				TNode child = output.at(i);
				int ci = contains.getIndex(child);
				vector<TNode> parentV = contains.getParent(ci);
				for (int j=0; j<parentV.size(); j++) {
					TNode parent = parentV.at(j);
					if (parent.getNodeType()==q.FirstElementName) {
						col1.push_back(parent.getIndex());
						if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
							col2.push_back(child.getProcLine());
						} else if (q.SecondElementType == "Constant") {
							int v = consTable.getConstant(child.getIndex());
							col2.push_back(v);
						} else if (q.SecondElementType == "StmtLst") {
							int pl = stmtLstTable.getStartLine(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "+") {
							int pl = plusTable.getPlus(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "-") {
							int pl = minusTable.getMinus(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "*") {
							int pl = timesTable.getTimes(child.getIndex());
							col2.push_back(pl);
						} else {
							col2.push_back(child.getIndex());
						}
					}
				}
			}
		} else if (isConstant(q.FirstElementName)) {
			// Constant cannot be the parent
		} else if (procTable.getProIndex(q.FirstElementName)!=-1) {
			int index = procTable.getProIndex(q.FirstElementName);
			for (int i=0; i<output.size(); i++) {
				TNode child = output.at(i);
				int ci = contains.getIndex(child);
				vector<TNode> parentV = contains.getParent(ci);
				for (int j=0; j<parentV.size(); j++) {
					TNode parent = parentV.at(j);
					if ((parent.getNodeType()=="Procedure") && (parent.getIndex()==index)) {
						col1.push_back(index);
						if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
							col2.push_back(child.getProcLine());
						} else if (q.SecondElementType == "Constant") {
							int v = consTable.getConstant(child.getIndex());
							col2.push_back(v);
						} else if (q.SecondElementType == "StmtLst") {
							int pl = stmtLstTable.getStartLine(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "+") {
							int pl = plusTable.getPlus(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "-") {
							int pl = minusTable.getMinus(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "*") {
							int pl = timesTable.getTimes(child.getIndex());
							col2.push_back(pl);
						} else {
							col2.push_back(child.getIndex());
						}
					}
				}
			}
		} else if (varTable.getVarIndex(q.FirstElementName)!=-1) {
			// variable cannot be the parent
		}
	} else if (q.FirstElementType == "Integer") {
		int c1 = atoi(q.FirstElementName.c_str());
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParent(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getProcLine()==c1) {
					col1.push_back(c1);
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (q.FirstElementType == "StmtLst") {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParent(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getNodeType()=="StmtLst") {
					int p = stmtLstTable.getStartLine(parent.getIndex());
					col1.push_back(p);
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (q.FirstElementName == "_") {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParent(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				col1.push_back(parent.getIndex());
				if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
					col2.push_back(child.getProcLine());
				} else if (q.SecondElementType == "Constant") {
					int v = consTable.getConstant(child.getIndex());
					col2.push_back(v);
				} else if (q.SecondElementType == "StmtLst") {
					int pl = stmtLstTable.getStartLine(child.getIndex());
					col2.push_back(pl);
				} else if (q.SecondElementType == "+") {
					int pl = plusTable.getPlus(child.getIndex());
					col2.push_back(pl);
				} else if (q.SecondElementType == "-") {
					int pl = minusTable.getMinus(child.getIndex());
					col2.push_back(pl);
				} else if (q.SecondElementType == "*") {
					int pl = timesTable.getTimes(child.getIndex());
					col2.push_back(pl);
				} else {
					col2.push_back(child.getIndex());
				}
			}
		}
	} else if (q.FirstElementType == "Statement") {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParent(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (isStatement(parent.getNodeType())) {
					col1.push_back(parent.getProcLine());
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (q.FirstElementType == "Procedure") {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParent(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getNodeType()=="Procedure") {
					col1.push_back(parent.getIndex());
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (q.FirstElementType == "Variable") {
		// variable cannot be parent
	} else if (q.FirstElementType == "Constant") {
		// constant cannot be parent
	} else if (isStatement(q.FirstElementType)) {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParent(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getNodeType()==q.FirstElementType) {
					col1.push_back(parent.getProcLine());
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (isOperation(q.FirstElementType)) {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParent(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getNodeType()==q.FirstElementType) {
					int p;
					if (q.FirstElementType=="+") {
						p = plusTable.getPlus(parent.getIndex());
					} else if (q.FirstElementType=="-") {
						p = minusTable.getMinus(parent.getIndex());
					} else if (q.FirstElementType=="*") {
						p = timesTable.getTimes(parent.getIndex());
					}
					col1.push_back(p);
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	}

	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

void QueryProcessor::queryContainsStar(funcQuery_t q) {
	queryTreeNode_t qtNode;
	qtNode.type = "Contains*";
	qtNode.numOfColumn = 2;
	qtNode.colName.push_back(q.FirstElementName);
	qtNode.colName.push_back(q.SecondElementName);

	Contains contains = (*pkb).getContains();
	ProcTable procTable = (*pkb).getProcTable();
	ConstTable consTable = (*pkb).getConstTable();
	VarTable varTable = (*pkb).getVarTable();
	StmtLstTable stmtLstTable = (*pkb).getStmtLstTable();
	PlusTable plusTable = (*pkb).getPlusTable();
	MinusTable minusTable = (*pkb).getMinusTable();
	TimesTable timesTable = (*pkb).getTimesTable();
	vector<int> col1, col2;

	vector<TNode> output; // record all the possible TNode for second arg
	//compute all the possible TNode for second arg first
	if (q.SecondElementType=="String"){
		if (isConstant(q.SecondElementName)) {
			int c2 = atoi(q.SecondElementName.c_str());
			int index = consTable.getConIndex(c2);
			output = contains.searchByIndex("Constant", index);
		} else if (isOperation(q.SecondElementName)) {
			output = contains.searchByType(q.SecondElementName);
		} else if (procTable.getProIndex(q.SecondElementName)!=-1) {
			int index = procTable.getProIndex(q.SecondElementName);
			output = contains.searchByIndex("Procedure", index);
		} else if (varTable.getVarIndex(q.SecondElementName)!=-1) {
			int index = varTable.getVarIndex(q.SecondElementName);
			output = contains.searchByIndex("Variable", index);
		}
	} else if (q.SecondElementType == "Integer") {
		int c2 = atoi(q.SecondElementName.c_str());
		output = contains.searchByProcline(c2);
	} else if (q.SecondElementType == "StmtLst") {
		output = contains.searchByType("StmtLst");
	} else if (q.SecondElementName == "_") {
		output = contains.getList();
	} else if (q.SecondElementType == "Statement") {
		vector<TNode> list = contains.getList();
		for (int i=0; i<list.size(); i++) {
			TNode temp = list.at(i);
			if (isStatement(temp.getNodeType())) {
				output.push_back(temp);
			}
		}
	} else if (q.SecondElementType == "Procedure") {
		output = contains.searchByType("Procedure");
	} else if (q.SecondElementType == "Variable") {
		output = contains.searchByType("Variable");
	} else if (q.SecondElementType == "Constant") {
		output = contains.searchByType("Constant");
	} else if (isStatement(q.SecondElementType)) {
		output = contains.searchByType(q.SecondElementType);
	} else if (isOperation(q.SecondElementType)) {
		output = contains.searchByType(q.SecondElementType);
	}

	//compute the result based on the output of second arg
	if (q.FirstElementType == "String") {
		if (isOperation(q.FirstElementName)) {
			for (int i=0; i<output.size(); i++) {
				TNode child = output.at(i);
				int ci = contains.getIndex(child);
				vector<TNode> parentV = contains.getParentStar(ci);
				for (int j=0; j<parentV.size(); j++) {
					TNode parent = parentV.at(j);
					if (parent.getNodeType()==q.FirstElementName) {
						col1.push_back(parent.getIndex());
						if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
							col2.push_back(child.getProcLine());
						} else if (q.SecondElementType == "Constant") {
							int v = consTable.getConstant(child.getIndex());
							col2.push_back(v);
						} else if (q.SecondElementType == "StmtLst") {
							int pl = stmtLstTable.getStartLine(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "+") {
							int pl = plusTable.getPlus(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "-") {
							int pl = minusTable.getMinus(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "*") {
							int pl = timesTable.getTimes(child.getIndex());
							col2.push_back(pl);
						} else {
							col2.push_back(child.getIndex());
						}
					}
				}
			}
		} else if (isConstant(q.FirstElementName)) {
			// Constant cannot be the parent
		} else if (procTable.getProIndex(q.FirstElementName)!=-1) {
			int index = procTable.getProIndex(q.FirstElementName);
			for (int i=0; i<output.size(); i++) {
				TNode child = output.at(i);
				int ci = contains.getIndex(child);
				vector<TNode> parentV = contains.getParentStar(ci);
				for (int j=0; j<parentV.size(); j++) {
					TNode parent = parentV.at(j);
					if ((parent.getNodeType()=="Procedure") && (parent.getIndex()==index)) {
						col1.push_back(index);
						if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
							col2.push_back(child.getProcLine());
						} else if (q.SecondElementType == "Constant") {
							int v = consTable.getConstant(child.getIndex());
							col2.push_back(v);
						} else if (q.SecondElementType == "StmtLst") {
							int pl = stmtLstTable.getStartLine(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "+") {
							int pl = plusTable.getPlus(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "-") {
							int pl = minusTable.getMinus(child.getIndex());
							col2.push_back(pl);
						} else if (q.SecondElementType == "*") {
							int pl = timesTable.getTimes(child.getIndex());
							col2.push_back(pl);
						} else {
							col2.push_back(child.getIndex());
						}
					}
				}
			}
		} else if (varTable.getVarIndex(q.FirstElementName)!=-1) {
			// variable cannot be the parent
		}
	} else if (q.FirstElementType == "Integer") {
		int c1 = atoi(q.FirstElementName.c_str());
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParentStar(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getProcLine()==c1) {
					col1.push_back(c1);
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (q.FirstElementType == "StmtLst") {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParentStar(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getNodeType()=="StmtLst") {
					int p = stmtLstTable.getStartLine(parent.getIndex());
					col1.push_back(p);
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (q.FirstElementName == "_") {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParentStar(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				col1.push_back(parent.getIndex());
				if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
					col2.push_back(child.getProcLine());
				} else if (q.SecondElementType == "Constant") {
					int v = consTable.getConstant(child.getIndex());
					col2.push_back(v);
				} else if (q.SecondElementType == "StmtLst") {
					int pl = stmtLstTable.getStartLine(child.getIndex());
					col2.push_back(pl);
				} else if (q.SecondElementType == "+") {
					int pl = plusTable.getPlus(child.getIndex());
					col2.push_back(pl);
				} else if (q.SecondElementType == "-") {
					int pl = minusTable.getMinus(child.getIndex());
					col2.push_back(pl);
				} else if (q.SecondElementType == "*") {
					int pl = timesTable.getTimes(child.getIndex());
					col2.push_back(pl);
				} else {
					col2.push_back(child.getIndex());
				}
			}
		}
	} else if (q.FirstElementType == "Statement") {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParentStar(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (isStatement(parent.getNodeType())) {
					col1.push_back(parent.getProcLine());
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (q.FirstElementType == "Procedure") {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParentStar(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getNodeType()=="Procedure") {
					col1.push_back(parent.getIndex());
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (q.FirstElementType == "Variable") {
		// variable cannot be parent
	} else if (q.FirstElementType == "Constant") {
		// constant cannot be parent
	} else if (isStatement(q.FirstElementType)) {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParentStar(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getNodeType()==q.FirstElementType) {
					col1.push_back(parent.getProcLine());
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	} else if (isOperation(q.FirstElementType)) {
		for (int i=0; i<output.size(); i++) {
			TNode child = output.at(i);
			int ci = contains.getIndex(child);
			vector<TNode> parentV = contains.getParentStar(ci);
			for (int j=0; j<parentV.size(); j++) {
				TNode parent = parentV.at(j);
				if (parent.getNodeType()==q.FirstElementType) {
					int p;
					if (q.FirstElementType=="+") {
						p = plusTable.getPlus(parent.getIndex());
					} else if (q.FirstElementType=="-") {
						p = minusTable.getMinus(parent.getIndex());
					} else if (q.FirstElementType=="*") {
						p = timesTable.getTimes(parent.getIndex());
					}
					col1.push_back(p);
					if ((q.SecondElementType=="Statement") || (isStatement(q.SecondElementType))) {
						col2.push_back(child.getProcLine());
					} else if (q.SecondElementType == "Constant") {
						int v = consTable.getConstant(child.getIndex());
						col2.push_back(v);
					} else if (q.SecondElementType == "StmtLst") {
						int pl = stmtLstTable.getStartLine(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "+") {
						int pl = plusTable.getPlus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "-") {
						int pl = minusTable.getMinus(child.getIndex());
						col2.push_back(pl);
					} else if (q.SecondElementType == "*") {
						int pl = timesTable.getTimes(child.getIndex());
						col2.push_back(pl);
					} else {
						col2.push_back(child.getIndex());
					}
				}
			}
		}
	}

	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}

// Pattern
bool QueryProcessor::areIdentical(vector<Pattern_node> t1,int index1, vector<Pattern_node> t2, int index2)
{
	// base cases
	if(	(t1.empty() || t1.size() == 0 || index1<0 || index1>=t1.size()) && 
		(t2.empty() || t2.size() == 0 || index2<0 || index2>=t2.size()) )
		return true;

	if( (t1.empty() || t1.size() == 0 || index1<0 || index1>=t1.size()) || 
		(t2.empty() || t2.size() == 0 || index2<0 || index2>=t2.size()) )
		return false;

	// Check if the data of both roots is same and data of left and right subtrees are also same
	return (t1.at(index1).getData() == t2.at(index2).getData() &&
		areIdentical(t1, t1.at(index1).getLeft(), t2, t2.at(index2).getLeft()) &&
		areIdentical(t1, t1.at(index1).getRight(), t2, t2.at(index2).getRight())	);
}
bool QueryProcessor::isSubtree(vector<Pattern_node> t1, int index1, vector<Pattern_node> t2, int index2){
	/* This function returns true if t1 is a subtree of t2, otherwise false */
	// base cases 
	if (t1.empty() || t1.size() == 0 || index1<0 || index1>=t1.size() )
        return true;
 
	if (t2.empty() || t2.size() == 0 || index2<0 || index2>=t2.size() )
        return false;
 
    // Check the tree with root as current node
    if (areIdentical(t1, index1, t2, index2))
        return true;
 
    // If the tree with root as current node doesn't match then try left and right subtrees one by one
	return isSubtree(t1, 0, t2, t2.at(index2).getLeft()) ||
		isSubtree(t1, 0, t2, t2.at(index2).getRight());
}
void QueryProcessor::queryPattern(patternQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "Pattern";
	
	vector<Pattern> pt = (*pkb).getPatternTable().getPatternTable();
	VarTable varTable = (*pkb).getVarTable();
	
	// 1st arg is variable reference
	if(!q.isVarRefVariable){
		qtNode.numOfColumn = 1;
		qtNode.colName.push_back(q.ElementName);
		vector<int> col;

		// Assign Pattern
		if(q.ElementType == "Assign"){
			// Pattern a (_,*)
			if(q.VarRef == "_"){
				// a(_,_)
				if(q.Expression.empty() || q.Expression.size() == 0){
					for(int i=0;i<pt.size();i++)
						if(pt.at(i).getType() == 0)
							col.push_back(pt.at(i).getLineNum());
				}
				// a(_,exp)
				else if(!q.ExpWithUnderscore){
					for(int i=0;i<pt.size();i++){
						if(pt.at(i).getType() == 0 && areIdentical(q.Expression, 0,pt.at(i).getNodeTree(),0))
							col.push_back(pt.at(i).getLineNum());
					}
				}
				// a(_,_exp_)
				else{
					for(int i=0;i<pt.size();i++){
						if(pt.at(i).getType() == 0 && isSubtree(q.Expression,0, pt.at(i).getNodeTree(),0))
							col.push_back(pt.at(i).getLineNum());
					}
				}
			}
			// Pattern a("",*)
			else{
				// a("",_)
				if(q.Expression.empty() || q.Expression.size() == 0){
					for(int i=0;i<pt.size();i++)
						if(pt.at(i).getType() == 0 && pt.at(i).getVarName() == q.VarRef)
							col.push_back(pt.at(i).getLineNum());
				}
				// a("",exp)
				else if(!q.ExpWithUnderscore){
					for(int i=0;i<pt.size();i++){
						if(pt.at(i).getType() == 0 && q.VarRef == pt.at(i).getVarName() && areIdentical(q.Expression,0, pt.at(i).getNodeTree(),0))
							col.push_back(pt.at(i).getLineNum());
					}
				}
				// a("",_exp_)
				else{
					for(int i=0;i<pt.size();i++){
						if(pt.at(i).getType() == 0 && q.VarRef == pt.at(i).getVarName() && isSubtree(q.Expression, 0,pt.at(i).getNodeTree(),0))
							col.push_back(pt.at(i).getLineNum());
					}
				}
			}
		}
		// Pattern while|if
		else{
			for(int i=0;i<pt.size();i++)
				if(patternType.at(pt.at(i).getType()) == q.ElementType && q.VarRef == pt.at(i).getVarName())
					col.push_back(pt.at(i).getLineNum());
		}

		qtNode.table.push_back(col);
	}
	// 1st arg not variable reference
	else{
		qtNode.numOfColumn = 2;
		qtNode.colName.push_back(q.ElementName);
		qtNode.colName.push_back(q.VarRef);

		vector<int> col1, col2;

		// Assign
		if(q.ElementType == "Assign"){
			// Pattern a (v,*)
			// a(v,_)
			if(q.Expression.empty() || q.Expression.size() == 0){
				for(int i=0;i<pt.size();i++)
					if(pt.at(i).getType() == 0){
						col1.push_back(pt.at(i).getLineNum());
						col2.push_back(varTable.getVarIndex(pt.at(i).getVarName()));
					}
			}
			// a(v,exp)
			else if(!q.ExpWithUnderscore){
				for(int i=0;i<pt.size();i++){
					if(pt.at(i).getType() == 0 && areIdentical(q.Expression, 0,pt.at(i).getNodeTree(),0)){
						col1.push_back(pt.at(i).getLineNum());
						col2.push_back(varTable.getVarIndex(pt.at(i).getVarName()));
					}
				}
			}
			// a(v,_exp_)
			else{
				for(int i=0;i<pt.size();i++){
					if(pt.at(i).getType() == 0 && isSubtree(q.Expression,0, pt.at(i).getNodeTree(),0)){
						col1.push_back(pt.at(i).getLineNum());
						col2.push_back(varTable.getVarIndex(pt.at(i).getVarName()));
					}
				}
			}
		}
		// While/If
		else{
			for(int i=0;i<pt.size();i++)
				if(patternType.at(pt.at(i).getType()) == q.ElementType){
					col1.push_back(pt.at(i).getLineNum());
					col2.push_back(varTable.getVarIndex(pt.at(i).getVarName()));
				}
		}
		qtNode.table.push_back(col1);
		qtNode.table.push_back(col2);
	}

	queryTree.push_back(qtNode);
}

// with-cl
void QueryProcessor::queryCompare(compareQuery_t q){
	queryTreeNode_t qtNode;
	qtNode.type = "with-cl";

	AST ast = (*pkb).getAST();
	StmtTable st = (*pkb).getStmtTable();
	ConstTable constTable = (*pkb).getConstTable();
	ProcTable procTable = (*pkb).getProcTable();
	VarTable varTable = (*pkb).getVarTable();
	vector<int> callProc = (*pkb).getCalleeList();
	int totalLineNum = (*pkb).getTotalLineNum();
	
	// int compare
	//// assign
	if(q.leftType == "Assign"){
		if(q.rightType == "Assign" || q.rightType == "Statement"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				if(st.getLineDetails(i).type == "Assign"){
					col1.push_back(i);
					col2.push_back(i);
				}
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Constant"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum && st.getLineDetails(n).type == "Assign")
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Integer"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;
			
			int n = atoi(q.rightName.c_str());
			if(n<=totalLineNum && st.getLineDetails(n).type == "Assign"){
				col1.push_back(n);
			}
			
			qtNode.table.push_back(col1);
		}
	}
	//////////////////////////////////////
	//// while
	else if(q.leftType == "While"){
		if(q.rightType == "While" || q.rightType == "Statement"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				if(st.getLineDetails(i).type == "While"){
					col1.push_back(i);
					col2.push_back(i);
				}
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Constant"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum && st.getLineDetails(n).type == "While")
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Integer"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;
			
			int n = atoi(q.rightName.c_str());
			if(n<=totalLineNum && st.getLineDetails(n).type == "While"){
				col1.push_back(n);
			}
			
			qtNode.table.push_back(col1);
		}
	}
	//////////////////////////////////////
	//// if
	else if(q.leftType == "If"){
		if(q.rightType == "If" || q.rightType == "Statement"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				if(st.getLineDetails(i).type == "If"){
					col1.push_back(i);
					col2.push_back(i);
				}
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Constant"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum && st.getLineDetails(n).type == "If")
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Integer"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;
			
			int n = atoi(q.rightName.c_str());
			if(n<=totalLineNum && st.getLineDetails(n).type == "If"){
				col1.push_back(n);
			}
			
			qtNode.table.push_back(col1);
		}
	}
	///////////////////////
	//// Call
	else if(q.leftType == "Call"){
		if(q.rightType == "Call" || q.rightType == "Statement"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				if(st.getLineDetails(i).type == "Call"){
					col1.push_back(i);
					col2.push_back(i);
				}
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Constant"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum && st.getLineDetails(n).type == "Call")
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Integer"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;
			
			int n = atoi(q.rightName.c_str());
			if(n<=totalLineNum && st.getLineDetails(n).type == "Call"){
				col1.push_back(n);
			}
			
			qtNode.table.push_back(col1);
		}
	}
	//////////////////////////////////////
	//// stmt
	else if(q.leftType == "Statement"){
		if(q.rightType == "Assign"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				if(st.getLineDetails(i).type == "Assign"){
					col1.push_back(i);
					col2.push_back(i);
				}
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "While"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				if(st.getLineDetails(i).type == "While"){
					col1.push_back(i);
					col2.push_back(i);
				}
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "If"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				if(st.getLineDetails(i).type == "If"){
					col1.push_back(i);
					col2.push_back(i);
				}
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "CallStmt"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				if(st.getLineDetails(i).type == "Call"){
					col1.push_back(i);
					col2.push_back(i);
				}
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Statement"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=1;i<=totalLineNum;i++){
				col1.push_back(i);
				col2.push_back(i);
			}
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Constant"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum)
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Integer"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;
			
			int n = atoi(q.rightName.c_str());
			if(n<=totalLineNum)
				col1.push_back(n);
			
			qtNode.table.push_back(col1);
		}
	}
	//////////////////////////////////////
	//// const
	else if(q.leftType == "Constant"){
		if(q.rightType == "Assign"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum && st.getLineDetails(n).type == "Assign")
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "While"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum && st.getLineDetails(n).type == "While")
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "If"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum && st.getLineDetails(n).type == "If")
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "CallStmt"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum && st.getLineDetails(n).type == "Call")
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Statement"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				if(n<=totalLineNum)
					col1.push_back(n);
					col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Constant"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<constTable.getSize();i++){
				int n = constTable.getConstant(i);
				col1.push_back(n);
				col2.push_back(n);
			}
	
			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Integer"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;

			int n = atoi(q.rightName.c_str());
			if(constTable.hasCon(n))
				col1.push_back(n);
	
			qtNode.table.push_back(col1);
		}
	}
	//////////////////////////////////////
	//// int
	else if(q.leftType == "Integer"){
		int n = atoi(q.leftName.c_str());
		if(q.rightType == "Assign"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			if(st.getLineDetails(n).type == "Assign")
				col1.push_back(n);

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "While"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			if(st.getLineDetails(n).type == "While")
				col1.push_back(n);

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "If"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			if(st.getLineDetails(n).type == "If")
				col1.push_back(n);

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "CallStmt"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			if(st.getLineDetails(n).type == "Call")
				col1.push_back(n);

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "Statement"){
			
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			col1.push_back(n);

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "Constant"){
			
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			if(constTable.hasCon(n))
				col1.push_back(n);

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "Integer"){
			int i = atoi(q.rightName.c_str());
			if(n == i)
				return;
			else{
				qtNode.numOfColumn = 0;
			}
		}
	}

	// string compare
	/////////////////
	//// Proc
	else if(q.leftType == "Procedure"){
		if(q.rightType == "Procedure"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<procTable.getSize();i++){
				col1.push_back(i);
				col2.push_back(i);
			}

			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "CallProc"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<callProc.size();i++){
				col1.push_back(callProc.at(i));
				col2.push_back(callProc.at(i));
			}

			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Variable"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<procTable.getSize();i++){
				for(int j=0;j<varTable.getSize();j++){
					if(procTable.getProName(i) == varTable.getVarName(j)){
						col1.push_back(i);
						col2.push_back(j);
					}
				}
			}

			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "String"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;

			for(int i=0;i<procTable.getSize();i++){
				if(procTable.getProName(i) == q.rightName){
					col1.push_back(i);
				}
			}

			qtNode.table.push_back(col1);
		}
	}
	///////////////
	//// callproc
	else if(q.leftType == "CallProc"){
		if(q.rightType == "CallProc"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<callProc.size();i++){
				col1.push_back(callProc.at(i));
				col2.push_back(callProc.at(i));
			}

			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Variable"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<callProc.size();i++){
				for(int j=0;j<varTable.getSize();j++){
					if(procTable.getProName(callProc.at(i)) == varTable.getVarName(j)){
						col1.push_back(callProc.at(i));
						col2.push_back(j);
					}
				}
			}

			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "String"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;

			for(int i=0;i<callProc.size();i++){
				if(procTable.getProName(callProc.at(i)) == q.rightName){
					col1.push_back(callProc.at(i));
				}
			}

			qtNode.table.push_back(col1);
		}
	}
	//////////////
	//// variable
	else if(q.leftType == "Variable"){
		if(q.rightType == "Procedure"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<procTable.getSize();i++){
				for(int j=0;j<varTable.getSize();j++){
					if(procTable.getProName(i) == varTable.getVarName(j)){
						col1.push_back(i);
						col2.push_back(j);
					}
				}
			}

			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "CallProc"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<callProc.size();i++){
				for(int j=0;j<varTable.getSize();j++){
					if(procTable.getProName(callProc.at(i)) == varTable.getVarName(j)){
						col1.push_back(callProc.at(i));
						col2.push_back(j);
					}
				}
			}

			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "Variable"){
			qtNode.numOfColumn = 2;
			qtNode.colName.push_back(q.leftName);
			qtNode.colName.push_back(q.rightName);
			vector<int> col1, col2;

			for(int i=0;i<varTable.getSize();i++){
				col1.push_back(i);
				col2.push_back(i);
			}

			qtNode.table.push_back(col1);
			qtNode.table.push_back(col2);
		}
		else if(q.rightType == "String"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.leftName);
			vector<int> col1;

			for(int i=0;i<varTable.getSize();i++){
				if(varTable.getVarName(i) == q.rightName){
					col1.push_back(i);
				}
			}

			qtNode.table.push_back(col1);
		}
	}
	///////////////
	//// string
	else if(q.leftType == "String"){
		if(q.rightType == "Procedure"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			for(int i=0;i<procTable.getSize();i++){
				if(procTable.getProName(i) == q.leftName){
					col1.push_back(i);
				}
			}

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "CallProc"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			for(int i=0;i<callProc.size();i++){
				if(procTable.getProName(callProc.at(i)) == q.leftName){
					col1.push_back(callProc.at(i));
				}
			}

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "Variable"){
			qtNode.numOfColumn = 1;
			qtNode.colName.push_back(q.rightName);
			vector<int> col1;

			for(int i=0;i<varTable.getSize();i++){
				if(varTable.getVarName(i) == q.leftName){
					col1.push_back(i);
				}
			}

			qtNode.table.push_back(col1);
		}
		else if(q.rightType == "String"){
			if(q.leftName == q.rightName)
				return;
			else qtNode.numOfColumn = 0;
		}
	}

	queryTree.push_back(qtNode);
}

// call.procName, call.stmt#
void QueryProcessor::buildCallRelationTable(string c){
	queryTreeNode_t qtNode;
	qtNode.type = "CallRelation";
	qtNode.numOfColumn = 2;
	
	strstream ss;
	ss << c << ".procname";
	string s;
	ss >> s;
	qtNode.colName.push_back(c);
	qtNode.colName.push_back(s);

	vector<int> col1,col2;

	Calls calls = (*pkb).getCalls();
	vector<Triple> callTable = calls.getCalls();
	for(int i=0;i<callTable.size();i++){
		col1.push_back(callTable.at(i).getFirst());
		col2.push_back(callTable.at(i).getThird());
	}

	qtNode.table.push_back(col1);
	qtNode.table.push_back(col2);
	queryTree.push_back(qtNode);
}



vector<string> QueryProcessor::findVarNames(vector<int> index){
	VarTable varTable = (*pkb).getVarTable();
	vector<string> varNames;
	int i;
	for(i=0;i<index.size();i++)
		varNames.push_back(varTable.getVarName(index.at(i)));
	return varNames;
}

bool QueryProcessor::hasVar(string v, vector<string> vList, int start, int end){
	int i;
	for(i=start;i<end;i++)
		if(v.compare(vList.at(i)) == 0)
			return true;
	return false;
}

bool QueryProcessor::isInList(int c, int v, vector<pair<int,int>> list){
	for(int i=0;i<list.size();i++)
		if(list.at(i).first == c && list.at(i).second == v)
			return true;
	return false;
}

list<string> QueryProcessor::convert(vector<int> v) {
	list<string> result;
	for (int i=0; i<v.size(); i++) {
		strstream ss;
		string s;
		ss << v[i];
		ss >> s;
		result.push_back(s);
	}
	return result;
}

list<string> QueryProcessor::convert(vector<string> v) {
	list<string> result;
	for (int i=0; i<v.size(); i++) {
		strstream ss;
		string s;
		ss << v[i];
		ss >> s;
		result.push_back(s);
	}
	return result;
}



// Query Evaluator functions
queryTreeNode_t QueryProcessor::mergeTable(queryTreeNode_t t1,queryTreeNode_t t2){
	vector<int> CommonIndexFort1,CommonIndexFort2;
	int NumOfCommonName=0;
	queryTreeNode_t result;
	if(t1.numOfColumn==2){
		if(t1.colName.at(0).compare(t1.colName.at(1))==0){
			t1.numOfColumn = 1;
			string singleValue = t1.colName.at(0); 
			t1.colName = vector<string>();
			t1.colName.push_back(singleValue);
			vector<int> singleTable = t1.table.at(0);
			t1.table = vector<vector<int>>();
			t1.table.push_back(singleTable);
		}
	}
	if(t2.numOfColumn==2){
		if(t2.colName.at(0).compare(t2.colName.at(1))==0){
			t2.numOfColumn = 1;
			string singleValue = t2.colName.at(0); 
			t2.colName = vector<string>();
			t2.colName.push_back(singleValue);
			vector<int> singleTable = t2.table.at(0);
			t2.table = vector<vector<int>>();
			t2.table.push_back(singleTable);
		}
	}
	//rearrange two table
	if((t2.numOfColumn>0)&&(!t2.table.empty())&&(!t2.table.at(0).empty())){
		for(int i=0;i<t1.numOfColumn;i++){
			for(int j=0;j<t2.numOfColumn;j++){
			    if(t1.colName.at(i).compare (t2.colName.at(j))==0){
				    string tempt1ColNamei=t1.colName.at(i);
				    string tempt1ColNameC=t1.colName.at(NumOfCommonName);
				    t1.colName.at(NumOfCommonName)=tempt1ColNamei;
				    t1.colName.at(i)=tempt1ColNameC;

					vector<int> tempt1Tablei=t1.table.at(i);
					vector<int> tempt1TableC=t1.table.at(NumOfCommonName);
					t1.table.at(NumOfCommonName)=tempt1Tablei;
				    t1.table.at(i)=tempt1TableC;

					string tempt2ColNamej=t2.colName.at(j);
					string tempt2ColNameC=t2.colName.at(NumOfCommonName);				
					t2.colName.at(NumOfCommonName)=tempt2ColNamej;				
					t2.colName.at(j)=tempt2ColNameC;

					vector<int> tempt2Tablej=t2.table.at(j);
					vector<int> tempt2TableC=t2.table.at(NumOfCommonName);
					t2.table.at(NumOfCommonName)=tempt2Tablej;
				    t2.table.at(j)=tempt2TableC;

					NumOfCommonName++;
				}
			}
		}
	}
	vector<string> tempCommonCol;
	for(int su=0;su<NumOfCommonName;su++){
		tempCommonCol.push_back(t1.colName.at(su));
	}
	commonCol = tempCommonCol;
	
	if((t2.numOfColumn==0)||(t2.table.empty())||(t2.table.at(0).empty())||(t2.table.at(0).size()==0)){	
		result.numOfColumn=0;
		return result;
	}
	/*
	//check
	cout<<"t1"<<endl;
	for(int i=0;i<t1.numOfColumn;i++){
		cout<<t1.colName.at(i).c_str()<<" ";
	}
	cout<<endl;
	for(int i=0;i<t1.table.at(0).size();i++){
		for(int j=0;j<t1.numOfColumn;j++){
			cout<<t1.table.at(j).at(i)<<" ";
		}
		cout<<endl;
	}
	cout<<endl;
	cout<<"t2"<<endl;
	for(int i=0;i<t2.numOfColumn;i++){
		cout<<t2.colName.at(i).c_str()<<" ";
	}
	cout<<endl;
	for(int i=0;i<t2.table.at(0).size();i++){
		for(int j=0;j<t2.numOfColumn;j++){
			cout<<t2.table.at(j).at(i)<<" ";
		}
		cout<<endl;
	}
	cout<<endl;
	cout<<"check end"<<endl;
	*/
	result.numOfColumn=t1.numOfColumn+t2.numOfColumn-NumOfCommonName;

	//------------------------
	//choose common rows
	for(int i=0;i<t1.table.at(0).size();i++){
		for(int j=0;j<t2.table.at(0).size();j++){
			bool EqualFlag = true;
			for(int k=0;k<NumOfCommonName;k++){
				if(t1.table.at(k).at(i) != t2.table.at(k).at(j)){
					EqualFlag = false;
					break;
				}
			}
			if(EqualFlag==true){
				CommonIndexFort1.push_back(i);
				CommonIndexFort2.push_back(j);
			}
		}
	}
	//------------
	
	//merge
	//first deal with colName
	for(int i=0;i<NumOfCommonName;i++){
		result.colName.push_back(t1.colName.at(i));
	}
	for(int i=NumOfCommonName;i<t1.numOfColumn;i++){
		result.colName.push_back(t1.colName.at(i));
	}
	for(int i=NumOfCommonName;i<t2.numOfColumn;i++){
		result.colName.push_back(t2.colName.at(i));
	}
	
	//second deal with table
	for(int i=0;i<result.numOfColumn;i++){
		result.table.push_back(vector<int>());
	}
	
	for(int i=0;i<CommonIndexFort1.size();i++){
		for(int j=0;j<t1.numOfColumn;j++){
			result.table.at(j).push_back(t1.table.at(j).at(CommonIndexFort1.at(i)));
		}
		int j=t1.numOfColumn;
		for(int k=NumOfCommonName;k<t2.numOfColumn;k++){
			result.table.at(j).push_back(t2.table.at(k).at(CommonIndexFort2.at(i)));
			j++;
		}
	}
	
	return result;
}




// Total processing
void QueryProcessor::queryPreprocessor(){
	queryParser();
	//cout<<queries.patternQueries.at(0).ExpWithUnderscore<<endl;
	/*
	cout<<queries.patternQueries.at(0).ElementType<<" "<<queries.patternQueries.at(0).ElementName<<" "<<queries.patternQueries.at(0).VarRef<< endl;
	cout<<queries.patternQueries.at(0).Expression.size()<<endl;
	*/
	buildTable();
}

bool QueryProcessor::haveCommonFactor(queryTreeNode_t t1,queryTreeNode_t t2){
	bool flag = false;
	for(int i=0;i<t1.numOfColumn;i++){
		for(int j=0;j<t2.numOfColumn;j++){
			if(t1.colName.at(i).compare(t2.colName.at(j))==0){
				flag = true;
				break;
			}
		}
	}
	return flag;
}
void QueryProcessor::buildNodeIntoTree(int thisNode,vector<queryTreeNode_t> queryTree,vector<int>* inTree,vector<vector<int>>* orderTree,bool isInMajorTree,int majorCount,vector<vector<int>>* majorTreeList,int normalCount,vector<vector<int>>* normalTreeList){
	if(isInMajorTree){
		if(majorCount>=(*majorTreeList).size()){
			(*majorTreeList).push_back(vector<int>());
			(*majorTreeList).at(majorCount).push_back(thisNode);
		}else{
			(*majorTreeList).at(majorCount).push_back(thisNode);
		}
	}
	else{
		if(normalCount>=(*normalTreeList).size()){
			(*normalTreeList).push_back(vector<int>());
			(*normalTreeList).at(normalCount).push_back(thisNode);
		}else{
			(*normalTreeList).at(normalCount).push_back(thisNode);
		}
	}
	for(int i=0;i<queryTree.size();i++){
		if((*inTree).at(i)==0&&haveCommonFactor(queryTree.at(i),queryTree.at(thisNode))){
			(*inTree).at(i)=1;
			buildNodeIntoTree(i,queryTree,inTree,orderTree,isInMajorTree,majorCount,majorTreeList,normalCount,normalTreeList);
			(*orderTree).at(thisNode).push_back(i);
		}
	}
}
void QueryProcessor::orderOfMajorTree(int root,vector<vector<int>> orderTree,vector<int>* result){
	for(int i=0;i<orderTree.at(root).size();i++){
		(*result).push_back(orderTree.at(root).at(i));
		orderOfMajorTree(orderTree.at(root).at(i),orderTree,result);
	}
}

list<string> QueryProcessor::queryEvaluator(){
	VarTable varTable = (*pkb).getVarTable();
	ProcTable procTable = (*pkb).getProcTable();
	queryTreeNode_t finalTable;
	vector<int> inTree;
	vector<vector<int>> orderTree;
	vector<int> rootNodesInOrderTree;
	vector<vector<int>> majorTreeList;
	int majorCount = 0;
	vector<vector<int>> normalTreeList;
	int normalCount = 0;
	//bug may occur
	vector<string> selectList;

	for(int i=0;i<queryTree.size();i++){
		if(queryTree.at(i).type.compare("Select")==0){
			selectList.push_back(queryTree.at(i).colName.at(0));
		}
	}
	
	//-------------
	bool withFalse = false;
	for(int iy=0;iy<queryTree.size();iy++){
		if(queryTree.at(iy).numOfColumn==0||queryTree.at(iy).table.at(0).size()==0){
			withFalse = true;
			break;
		}
	}

	vector<string> colName;
	vector<int> colCount;
	if(queryTree.size()>1&&withFalse==false){
		for(int i=0;i<queryTree.size();i++){
			if(queryTree.at(i).numOfColumn==1){
				if((queryTree.at(i).colName.at(0).compare("_")==0||isdigit(queryTree.at(i).colName.at(0)[0]))&&(queryTree.at(i).type.compare("Select")!=0)){				 
					queryTree.erase(queryTree.begin()+i);
					i--;
				}else{
					bool contain = false;
					for(int h=0;h<colName.size();h++){
						if(queryTree.at(i).colName.at(0).compare(colName.at(h))==0){
							contain = true;
							colCount.at(h)++;
						}
					}
					if(contain == false){
						colName.push_back(queryTree.at(i).colName.at(0));
						colCount.push_back(0);
					}

				}

			}else{
				//col == 2
				if((queryTree.at(i).colName.at(0).compare("_")==0||isdigit(queryTree.at(i).colName.at(0)[0]))&&(queryTree.at(i).colName.at(1).compare("_")==0||isdigit(queryTree.at(i).colName.at(1)[0]))){
					queryTree.erase(queryTree.begin()+i);
					i--;
				}else{
					if(queryTree.at(i).colName.at(0).compare("_")==0||isdigit(queryTree.at(i).colName.at(0)[0])){
						queryTree.at(i).numOfColumn=1;
						queryTree.at(i).colName.erase(queryTree.at(i).colName.begin());
						queryTree.at(i).table.erase(queryTree.at(i).table.begin());
						vector<int> temp;
						for(int ki=0;ki<queryTree.at(i).table.at(0).size();ki++){
							bool inSide = false;
							for(int kj=0;kj<temp.size();kj++){
								if(temp.at(kj)==queryTree.at(i).table.at(0).at(ki)){
									inSide =true;
									break;
								}
							}
							if(inSide==false){
								temp.push_back(queryTree.at(i).table.at(0).at(ki));
							}
						}
						queryTree.at(i).table.at(0) = temp;
						bool contain = false;
						for(int h=0;h<colName.size();h++){
							if(queryTree.at(i).colName.at(0).compare(colName.at(h))==0){
								contain = true;
								colCount.at(h)++;
								break;
							}
						}
						if(contain == false){
							colName.push_back(queryTree.at(i).colName.at(0));
							colCount.push_back(0);
						}

					}else{
						if(queryTree.at(i).colName.at(1).compare("_")==0||isdigit(queryTree.at(i).colName.at(1)[0])){
							queryTree.at(i).numOfColumn=1;
							queryTree.at(i).colName.erase(queryTree.at(i).colName.begin()+1);
							queryTree.at(i).table.erase(queryTree.at(i).table.begin()+1);
							vector<int> temp;
							for(int ki=0;ki<queryTree.at(i).table.at(0).size();ki++){
								bool inSide = false;
								for(int kj=0;kj<temp.size();kj++){
									if(temp.at(kj)==queryTree.at(i).table.at(0).at(ki)){
										inSide =true;
										break;
									}
								}
								if(inSide==false){
									temp.push_back(queryTree.at(i).table.at(0).at(ki));
								}
							}
							queryTree.at(i).table.at(0) = temp;
							bool contain = false;
							for(int h=0;h<colName.size();h++){
								if(queryTree.at(i).colName.at(0).compare(colName.at(h))==0){
									contain = true;
									colCount.at(h)++;
								}
							}
							if(contain == false){
								colName.push_back(queryTree.at(i).colName.at(0));
								colCount.push_back(0);
							}
						}else{
							bool contain = false;
							for(int h=0;h<colName.size();h++){
								if(queryTree.at(i).colName.at(0).compare(colName.at(h))==0){
									contain = true;
									colCount.at(h)++;
								}
							}
							if(contain == false){
								colName.push_back(queryTree.at(i).colName.at(0));
								colCount.push_back(0);
							}

							contain = false;
							for(int h=0;h<colName.size();h++){
								if(queryTree.at(i).colName.at(1).compare(colName.at(h))==0){
									contain = true;
									colCount.at(h)++;
								}
							}
							if(contain == false){
								colName.push_back(queryTree.at(i).colName.at(1));
								colCount.push_back(0);
							}
						}
					}
				}
			}
		}

		for(int i=0;i<queryTree.size();i++){
			if((queryTree.at(i).numOfColumn==1)){
				if(queryTree.at(i).type.compare("Select")!=0){
					int cy;
					for(cy=0;cy<colName.size();cy++){
						if(queryTree.at(i).colName.at(0).compare(colName.at(cy))==0){
							break;
						}
					}
					if(colCount.at(cy)==0){
						queryTree.erase(queryTree.begin()+i);
					}
				}
			}else{
				int cy1,cy2;
				for(cy1=0;cy1<colName.size();cy1++){
					if(queryTree.at(i).colName.at(0).compare(colName.at(cy1))==0){
						break;
					}
				}
				for(cy2=0;cy2<colName.size();cy2++){
					if(queryTree.at(i).colName.at(1).compare(colName.at(cy2))==0){
						break;
					}
				}
				if((colCount.at(cy1)==0)&&(colCount.at(cy2)==0)){
					queryTree.erase(queryTree.begin()+i);
				}else{
					if(colCount.at(cy1)==0){
						queryTree.at(i).numOfColumn=1;
						queryTree.at(i).colName.erase(queryTree.at(i).colName.begin());
						queryTree.at(i).table.erase(queryTree.at(i).table.begin());
						vector<int> temp;
						for(int ki=0;ki<queryTree.at(i).table.at(0).size();ki++){
							bool inSide = false;
							for(int kj=0;kj<temp.size();kj++){
								if(temp.at(kj)==queryTree.at(i).table.at(0).at(ki)){
									inSide =true;
									break;
								}
							}
							if(inSide==false){
								temp.push_back(queryTree.at(i).table.at(0).at(ki));
							}
						}
						queryTree.at(i).table.at(0) = temp;
					}else{
						if(colCount.at(cy2)==0){
							queryTree.at(i).numOfColumn=1;
							queryTree.at(i).colName.erase(queryTree.at(i).colName.begin()+1);
							queryTree.at(i).table.erase(queryTree.at(i).table.begin()+1);
							vector<int> temp;
							for(int ki=0;ki<queryTree.at(i).table.at(0).size();ki++){
								bool inSide = false;
								for(int kj=0;kj<temp.size();kj++){
									if(temp.at(kj)==queryTree.at(i).table.at(0).at(ki)){
										inSide =true;
										break;
									}
								}
								if(inSide==false){
									temp.push_back(queryTree.at(i).table.at(0).at(ki));
								}
							}
							queryTree.at(i).table.at(0) = temp;
						}
					}
				}
			}
		}
	}
 	for(int i=0;i<queryTree.size();i++){
		inTree.push_back(0);
		orderTree.push_back(vector<int>());
	}
	
	for(int i=0;i<queryTree.size();i++){
		if(inTree.at(i)==0){
			rootNodesInOrderTree.push_back(i);
		    inTree.at(i)=1;
			bool isInMajprTree = false;
			if(queryTree.at(i).type.compare("Select")==0)
				isInMajprTree = true;
			buildNodeIntoTree(i,queryTree,&inTree,&orderTree,isInMajprTree, majorCount,&majorTreeList,normalCount, &normalTreeList);
			if(isInMajprTree){
				majorCount++;
			} else{
				normalCount++;
			}
		}
	}
	//if any node is empty, then result is empty
	bool needMerge = true;
	for(int i=0;i<queryTree.size();i++){
		if((queryTree.at(i).numOfColumn==0)||(queryTree.at(i).table.at(0).empty())){
			needMerge = false;
			break;
		}
	}
	if(queryTree.size()==0||withFalse == true){
		needMerge = false;
	}
	if(needMerge ==true){
		switch(selectType){
		case 1:case 2:case 4:case 5:case 6:{
			vector<queryTreeNode_t> majorResult;
			bool noNeedMajor = false;
			vector<int> toMerge;
			for(int i=0;i<rootNodesInOrderTree.size();i++){//deal with normal tree
				if(!queryTree.at(i).type.compare("Select")==0){
					orderOfMajorTree(rootNodesInOrderTree.at(i),orderTree,&toMerge);
					finalTable = queryTree.at(rootNodesInOrderTree.at(i));
					int mergeCount=0;
					while(mergeCount<toMerge.size()){
						if((queryTree.at(toMerge.at(mergeCount)).numOfColumn==2)&&(queryTree.at(toMerge.at(mergeCount)).colName.at(0).compare("_")==0)&&(queryTree.at(toMerge.at(mergeCount)).colName.at(1).compare("_")==0)){
						    mergeCount++;
						}else {
							finalTable =  mergeTable(finalTable,queryTree.at(toMerge.at(mergeCount)));
							if((finalTable.numOfColumn==0)||(finalTable.table.empty())||(finalTable.table.at(0).size()==0)){
								break;
							}
							//remove duplicate
							for(int yf=0;yf<finalTable.table.at(0).size();yf++){
								for(int yg=yf+1;yg<finalTable.table.at(0).size();yg++){
									bool twoAreEQ = true;
									for(int gu=0;gu<finalTable.numOfColumn;gu++){
										if(finalTable.table.at(gu).at(yf)!=finalTable.table.at(gu).at(yg)){
											twoAreEQ=false;
											break;
										}
									}
									if(twoAreEQ == true){
										for(int gu=0;gu<finalTable.numOfColumn;gu++){
											finalTable.table.at(gu).erase(finalTable.table.at(gu).begin()+yg);
										}
									}
							    }
							}
							//-----------
							if(queryTree.size()>1){
								//bug may occur
								for(int st=0;st<commonCol.size();st++){
									for(int sw=0;sw<colName.size();sw++){
										if(commonCol.at(st).compare(colName.at(sw))==0){
											colCount.at(sw)--;
											if(colCount.at(sw)<=0){
												//remove
												int ts;
												for(ts=0;ts<selectList.size();ts++){
													if(selectList.at(ts).compare(colName.at(sw))==0)
														break;
												}
												if(ts==selectList.size()&&finalTable.numOfColumn>1){
													//sure to remove
													for(int th=0;th<finalTable.numOfColumn;th++){
														if(finalTable.colName.at(th).compare(colName.at(sw))==0){
															finalTable.numOfColumn--;
															finalTable.colName.erase(finalTable.colName.begin()+th);
															finalTable.table.erase(finalTable.table.begin()+th);
															for(int ti=0;ti<finalTable.table.at(0).size();ti++){
																for(int to=ti+1;to<finalTable.table.at(0).size();to++){
																	bool finalEq = true;
																	for(int tp=0;tp<finalTable.numOfColumn;tp++){
																		if(finalTable.table.at(tp).at(ti)!=finalTable.table.at(tp).at(to)){
																			finalEq = false;
																			break;
																		}
																	}
																	if(finalEq==true){
																		for(int tf=0;tf<finalTable.numOfColumn;tf++){
																			finalTable.table.at(tf).erase(finalTable.table.at(tf).begin()+to);
																		} 
																	}
																}
															}
															break;
														}

													}
												}
											}
											break;
										}
									}
								}
								//----------
							}
							mergeCount++;
						}
					}
					if((finalTable.numOfColumn==0)||(finalTable.table.empty())||(finalTable.table.at(0).size()==0)){
						noNeedMajor = true;
						break;
					}
				}
			}
			if(noNeedMajor ==true){
				finalTable.colName = queryTree.at(0).colName;
				finalTable.numOfColumn = queryTree.at(0).numOfColumn;
				finalTable.type = queryTree.at(0).type;
				for(int i=0;i<finalTable.numOfColumn;i++){
					finalTable.table.push_back(vector<int>());
				}
			}else{
				bool internalZero = false;
				for(int i=0;i<rootNodesInOrderTree.size();i++){//deal with major tree
					if(queryTree.at(i).type.compare("Select")==0){
						orderOfMajorTree(rootNodesInOrderTree.at(i),orderTree,&toMerge);
						finalTable = queryTree.at(rootNodesInOrderTree.at(i));
						int mergeCount=0;
						while(mergeCount<toMerge.size()){
							finalTable =  mergeTable(finalTable,queryTree.at(toMerge.at(mergeCount)));
							if((finalTable.numOfColumn==0)||(finalTable.table.empty())||(finalTable.table.at(0).size()==0)){
								internalZero = true;
								break;
							}
							//remove duplicate
							for(int yf=0;yf<finalTable.table.at(0).size();yf++){
								for(int yg=yf+1;yg<finalTable.table.at(0).size();yg++){
									bool twoAreEQ = true;
									for(int gu=0;gu<finalTable.numOfColumn;gu++){
										if(finalTable.table.at(gu).at(yf)!=finalTable.table.at(gu).at(yg)){
											twoAreEQ=false;
											break;
										}
									}
									if(twoAreEQ == true){
										for(int gu=0;gu<finalTable.numOfColumn;gu++){
											finalTable.table.at(gu).erase(finalTable.table.at(gu).begin()+yg);
										}
									}
							    }
							}
							//-----------
							if(queryTree.size()>1){
								//bug may occur
								for(int st=0;st<commonCol.size();st++){
									for(int sw=0;sw<colName.size();sw++){
										if(commonCol.at(st).compare(colName.at(sw))==0){
											colCount.at(sw)--;
											if(colCount.at(sw)<=0){
												//remove
												int ts;
												for(ts=0;ts<selectList.size();ts++){
													if(selectList.at(ts).compare(colName.at(sw))==0)
														break;
												}
												if(ts==selectList.size()&&finalTable.numOfColumn>1){
													//sure to remove
													for(int th=0;th<finalTable.numOfColumn;th++){
														if(finalTable.colName.at(th).compare(colName.at(sw))==0){
															finalTable.numOfColumn--;
															finalTable.colName.erase(finalTable.colName.begin()+th);
															finalTable.table.erase(finalTable.table.begin()+th);
															for(int ti=0;ti<finalTable.table.at(0).size();ti++){
																for(int to=ti+1;to<finalTable.table.at(0).size();to++){
																	bool finalEq = true;
																	for(int tp=0;tp<finalTable.numOfColumn;tp++){
																		if(finalTable.table.at(tp).at(ti)!=finalTable.table.at(tp).at(to)){
																			finalEq = false;
																			break;
																		}
																	}
																	if(finalEq==true){
																		for(int tf=0;tf<finalTable.numOfColumn;tf++){
																			finalTable.table.at(tf).erase(finalTable.table.at(tf).begin()+to);
																		} 
																	}
																}
															}
															break;
														}

													}
												}
											}
											break;
										}
									}
								}
								//----------
							}
							mergeCount++;
						}
						majorResult.push_back(finalTable);
					}
				}
				if(internalZero == true){
					finalTable.numOfColumn=0;
				}else{
				finalTable = majorResult.at(0);
				for(int i=1;i<majorResult.size();i++){
					finalTable =  mergeTable(finalTable,majorResult.at(i));
					/*
					//remove duplicate
					for(int yf=0;yf<finalTable.table.at(0).size();yf++){
						for(int yg=yf+1;yg<finalTable.table.at(0).size();yg++){
							bool twoAreEQ = true;
							for(int gu=0;gu<finalTable.numOfColumn;gu++){
								if(finalTable.table.at(gu).at(yf)!=finalTable.table.at(gu).at(yg)){
									twoAreEQ=false;
									break;
								}
							}
							if(twoAreEQ == true){
								for(int gu=0;gu<finalTable.numOfColumn;gu++){
									finalTable.table.at(gu).erase(finalTable.table.at(gu).begin()+yg);
								}
							}
						}
					}
					//-----------
					*/
				}
			}
				}
			break;
			   }
	    case 3:{
		//all tree are (sub)major trees,all submajor Trees need to be merged
			for(int i=0;i<rootNodesInOrderTree.size();i++){
				vector<int> toMerge;
				orderOfMajorTree(rootNodesInOrderTree.at(i),orderTree,&toMerge);
				finalTable = queryTree.at(rootNodesInOrderTree.at(i));
				int mergeCount = 0;
				while((mergeCount<toMerge.size())&&(finalTable.numOfColumn!=0)&&(!finalTable.table.empty())&&(finalTable.table.at(0).size()!=0)){
				    finalTable =  mergeTable(finalTable,queryTree.at(toMerge.at(mergeCount)));
					if(queryTree.size()>1){
						//bug may occur
						for(int st=0;st<commonCol.size();st++){
							for(int sw=0;sw<colName.size();sw++){
								if(commonCol.at(st).compare(colName.at(sw))==0){
									colCount.at(sw)--;
									if(colCount.at(sw)<=0){
										//remove
										int ts;
										for(ts=0;ts<selectList.size();ts++){
											if(selectList.at(ts).compare(colName.at(sw))==0)
												break;
										}
										if(ts==selectList.size()&&finalTable.numOfColumn>1){
											//sure to remove
											for(int th=0;th<finalTable.numOfColumn;th++){
												if(finalTable.colName.at(th).compare(colName.at(sw))==0){
													finalTable.numOfColumn--;
													finalTable.colName.erase(finalTable.colName.begin()+th);
													finalTable.table.erase(finalTable.table.begin()+th);
													for(int ti=0;ti<finalTable.table.at(0).size();ti++){
														for(int to=ti+1;to<finalTable.table.at(0).size();to++){
															bool finalEq = true;
															for(int tp=0;tp<finalTable.numOfColumn;tp++){
																if(finalTable.table.at(tp).at(ti)!=finalTable.table.at(tp).at(to)){
																	finalEq = false;
																	break;
																}
															}
															if(finalEq==true){
																for(int tf=0;tf<finalTable.numOfColumn;tf++){
																	finalTable.table.at(tf).erase(finalTable.table.at(tf).begin()+to);
																} 
															}
														}
													}
													break;
												}
											}
										}
									}
									break;
								}
							}
						}
						//----------
					}
				    mergeCount++;
			    }
				if((finalTable.numOfColumn==0)||(finalTable.table.empty())||(finalTable.table.at(0).size()==0)){
					break;
				}
			}
		    break;
		}
	    default:
		    break;
	    }
	}
	else{
		finalTable.numOfColumn = 0;
		if(queryTree.size()==0){
			finalTable.numOfColumn =1;
			finalTable.type="with";
			finalTable.colName.push_back("with");
			finalTable.table.push_back(vector<int>());
			finalTable.table.at(0).push_back(-1);
		}
	}
	
	// Get results
	switch(selectType){
	case 1:{	
		vector<int> rBuffer;
		for(int i=0;i<finalTable.numOfColumn;i++){
			if(finalTable.colName.at(i).compare(selectedArgName) == 0){
				for(int j=0;j<finalTable.table.at(i).size();j++)
					rBuffer.push_back(finalTable.table.at(i).at(j));
				break;
			}
		}

		vector<int> result = rBuffer;
		return convert(result);
		break;
		   }
	case 2:{
		vector<int> rBuffer;
		for(int i=0;i<finalTable.numOfColumn;i++){
			if(finalTable.colName.at(i).compare(selectedArgName) == 0)
				for(int j=0;j<finalTable.table.at(i).size();j++)
					rBuffer.push_back(finalTable.table.at(i).at(j));
		}

		vector<string> result;
		for(int i=0;i<rBuffer.size();i++)
			result.push_back(varTable.getVarName(rBuffer.at(i)));
		return convert(result);
		break;
		   }
	case 3:{
		list<string> result;

		if(finalTable.numOfColumn == 0 || finalTable.table.empty() || finalTable.table.at(0).size() == 0)
			result.push_back("False");
		else result.push_back("True");
		return result;
		break;
		   }
	case 4:{
		vector<int> rBuffer;
		for(int i=0;i<finalTable.numOfColumn;i++){
			if(finalTable.colName.at(i).compare(selectedArgName) == 0)
				for(int j=0;j<finalTable.table.at(i).size();j++)
					rBuffer.push_back(finalTable.table.at(i).at(j));
		}

		vector<string> result;
		for(int i=0;i<rBuffer.size();i++)
			result.push_back(procTable.getProName(rBuffer.at(i)));
		return convert(result);
		break;
		   }
	case 5:{
		vector<vector<int>> rBuffer;
		vector<string> colType;
		list< string > result = list< string >();
		
		for(int i=0;i<queries.selectQuery.tupleName.size();i++){
			for(int j=0;j<finalTable.numOfColumn;j++)
				if(finalTable.colName.at(j) == queries.selectQuery.tupleName.at(i)){
					colType.push_back(queries.selectQuery.tupleType.at(i));
					rBuffer.push_back(finalTable.table.at(j));
				}
		}
		if(rBuffer.size() == queries.selectQuery.tupleName.size()){
			for(int j=0;j<rBuffer.at(0).size();j++){
				stringstream r;
				for(int i=0;i<rBuffer.size();i++){
					if(	colType.at(i) == "Assign" || colType.at(i) == "While" || colType.at(i) == "If" || colType.at(i) == "Statement" || colType.at(i) == "Call" || 
						colType.at(i) == "StmtLst" || colType.at(i) == "+" || colType.at(i) == "-" || colType.at(i) == "*")
						r << rBuffer.at(i).at(j);
					else if(colType.at(i) == "Procedure")
						r << procTable.getProName(rBuffer.at(i).at(j));
					else if(colType.at(i) == "Variable")
						r << varTable.getVarName(rBuffer.at(i).at(j));

					if(i != rBuffer.size()-1)
						r << " ";
				}
				result.push_back(r.str());
			}
		}
		
		return result;
		break;
		   }
	case 6:{
		vector<int> result;
		for(int i=0;i<finalTable.numOfColumn;i++){
			if(finalTable.colName.at(i).compare(selectedArgName) == 0)
				result = finalTable.table.at(i);
		}

		return convert(result);
		break;
		   }
	default:{
		break;
			}
	}
}



// Public functions
QueryProcessor::QueryProcessor(){
}

QueryProcessor::QueryProcessor(PKB* p){
	patternType.push_back("Assign");
	patternType.push_back("If");
	patternType.push_back("While");

	selectType = 0;

	pkb = p;
	affectsBip = AffectsBip(pkb);
}

list<string> QueryProcessor::processingQuery(string query){
	vector<string> vQuery = splitS(query, ';');
	string x_temp, y_temp;
	int size = vQuery.size();
	x_temp = "";
	for (int i =0; i<size-1; i++) {
		x_temp = x_temp + vQuery[i] + ";";
	}
	y_temp = trimL(vQuery[size-1]);
	// Reset the value.
	_query = pair<string,string>(x_temp, y_temp);

	queryPreprocessor();
	return queryEvaluator();
}
